How Does Kotlin Generate Property from Java Getters and Setters (Undocumented by JetBrains)

Abhishek Luthra
Cashify Engineering
3 min readApr 1, 2018

Recently, I was migrating my existing Android Java project to Kotlin and I faced a bizarre issue while setting hint and text to EditText programmatically. It took me some time to find the reason behind it, but let me first present the problem to you.

val editText = EditText()
  1. Setting Hint to EditText (working as expected)
  • Java way of setting hint to EditText

editText.setHint("This is my hint")
// Lint message: "Use property access syntax"
  • Kotlin way of setting hint to EditText
editText.hint = "This is my hint"   
// entirely okay

2. Setting Text to EditText ( a bit confusing at first sight)

  • Java way of setting text to EditText
editText.setText("This is my text")  
// entirely okay (no lint message)
  • Kotlin way of setting text to EditText
editText.text = "This is my text"  
// Type mismatch: inferred type is kotlin.String but //android.text.Editable! was expected

I was a little confused about this absurdity due to the different behaviour between the two. While setting text and hint to EditText using Kotlin property access syntax and calling Java getters and setters from Kotlin, the declaration showed identical signatures inherited from TextView:

public final void setHint(CharSequence hint)public final void setText(CharSequence text)

I had an initial impression that x.y = z was a shortcut for x.setY(z) but apparently that impression was wrong. setText() is treated as a normal method rather than a setter, but what was the difference between these two methods that made the compiler behave differently?

Reason ( seems like JetBrains forgot to document it in their “calling Java from Kotlin documentation”) :

Methods that follow the Java conventions for getters and setters (no-argument methods with names starting with ‘get’ and single-argument methods with names starting with ‘set’) are represented as properties in Kotlin.
However, while generating a property for a Java getter/setter pair, Kotlin looks for a getter first. The getter is enough to infer the type of property from the type of the getter. On the other hand, the property will not be created if only a setter is present (because Kotlin does not support set-only properties at this time).

When a setter comes into play, property generation process becomes ambiguous. The reason is that the getter and the setter may have different types. Moreover, the getter and/or the setter may be overridden in a subclass,
which exactly is the case of EditText in Android.

In the above case the Android TextView class contains a getter

CharSequence getText() 

and a setter

void setText(CharSequence)

If I had a variable of type TextView my code would have worked fine.
But I used the EditText class which had an overridden getter

Editable getText()

It means that you can get an Editable for an EditText and set an Editable to an EditText. Therefore, Kotlin reasonably creates a synthetic property text of type Editable. Considering that the String Class is not editable, I cannot assign a String instance to the text property of the EditText class.

It Seems like JetBrains forgot to specify this dominant role of getter methods while generating Kotlin properties for Java getter and setter methods. I have submitted the change in Official Kotlin documentation through GitHub . Anyway, I hope no one else would have to spend their time wondering how synthetic property generation in Kotlin works after reading this post.

--

--