Kotlin under the hood: The nuances of using annotations in Kotlin | by Max Sidorov | Dec, 2023
Kotlin is a very concise language, but when its code is compiled into Java bytecode, Kotlin’s elegant constructs disintegrate into Java’s monstrous constructs. At the same time, the use of annotations can play a cruel joke on you.
Let’s consider an example of @JsonProperty annotation and a regular data class. Let’s suppose that we have a data class like this
data class SomeData(@JsonProperty("id") val someDataId: String)
From the code it is logical to assume that the @JsonProperty annotation will be applied to the field someDataId, because we specify it for the field. Thus, our Json file should contain the “id” field instead of “someDataId” and it should work when reading and writing the file.
But is it so? Let’s look into it.
If we decompile Kotlin code, we will see that in Java this class looks like this:
public static final class SomeData {
@NotNull
// private field
private String someDataId; @NotNull
// field getter
public final String getSomeDataId() {
return this.someDataId;
}
// constructor with field param
public SomeData(@NotNull String someDataId) {
Intrinsics.checkNotNullParameter(someDataId, "someDataId");
super();
this.someDataId = someDataId;
}
As you can see, our someDataId field has been converted into a private field, a getter for the field, and a class constructor parameter. So which of these will the annotation be applied to?
If we look at the definition of the @JsonProperty annotation, we see that it can be applied to a private field, a method and a method parameter. That is, to all Java constructs into which our class data field is decomposed.
@Target({ElementType.ANNOTATION_TYPE,
ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonProperty
This results in a non-obviousness for the Kotlin compiler. It can apply our annotation to a field, a getter, and a constructor parameter. What do you think it will apply the annotation to in this particular case?
The correct answer is to the constructor parameter of the class.
The real bytecode will look like this and it clearly shows that our annotation applies only to the constructor parameter of the class:
public static final class SomeData {
@NotNull
private String someDataId;@NotNull
public final String getSomeDataId() {
return this.someDataId;
}
public SomeData(@JsonProperty("id") @NotNull String someDataId) {
Intrinsics.checkNotNullParameter(someDataId, "someDataId");
super();
this.someDataId = someDataId;
}
As a result, our class will be read correctly from Json, but Json generation by our class will not work correctly. When writing to Json, the field name will be “someDataId” instead of the expected “id”.
Let’s look into why Kotlin works this way.
To resolve such collisions in Kotlin, there is a special rule that says:
If an annotation can be applied to several language constructs at once, it will be applied by default to the first matching use-site from the list:
– Method Parameter
– Property (not available in Java)
– Field
And in order to explicitly resolve such collisions at the code level, Kotlin has a special syntax that allows you to explicitly specify the scope of the annotation.
@[use-site]:Annotation
Examples of specifying the scope of an annotation:
class Example(
@field:JsonProperty("Foo") val foo, // annotate Java field
@get:JsonProperty("Bar") val bar, // annotate Java getter
@param:JsonProperty("Some") val some // annotate Java constructor parameter
)
Here is a complete list of use-site types taken from the Kotlin documentation
· file
· property (annotations with this target are not visible to Java)
· field
· get (property getter)
· set (property setter)
· receiver (receiver parameter of an extension function or property)
· param (constructor parameter)
· setparam (property setter parameter)
· delegate (the field storing the delegate instance for a delegated property)
Related Posts
Leave a Reply Cancel reply
Categories
- ! Без рубрики (1)
- ++PU (1)
- 1 (1)
- 1w (1)
- 1win Brazil (1)
- 1win India (1)
- 1WIN Official In Russia (1)
- 1win Turkiye (1)
- 1xbet egypt (1)
- 2ankarafayansustasi.net_may (1)
- ankarafayansustasi.netsiteai apr (1)
- Artificial intelligence (1)
- Arts & Entertainment, Photography (1)
- belugasitesi_mAY (1)
- BH_TOPsitesi apr (1)
- BHsitesy_may (2)
- Blog (3)
- Bookkeeping (14)
- Bootcamp de programação (2)
- Bootcamp de programación (2)
- BT_TOPsitesi apr (1)
- casino (5)
- casinom-hub (1)
- casinom-hub.comsitesi apr (3)
- colombian mail order brides (1)
- Cryptocurrency exchange (2)
- Dinamobet_next (1)
- Disease & Illness, Colon Cancer (1)
- Dumanbet (1)
- Dumanbet_next (1)
- Finance, Insurance (1)
- FinTech (5)
- Forex Trading (11)
- Galabet (1)
- Health & Fitness, Fitness Equipment (1)
- Hitbet (1)
- Home & Family, Crafts (1)
- Home & Family, Gardening (1)
- Internet Business, Audio-Video Streaming (1)
- Internet Business, Ecommerce (1)
- Internet Business, Email Marketing (1)
- Internet Business, Internet Marketing (1)
- IT Вакансії (1)
- IT Образование (5)
- IT Освіта (1)
- latin women dating (1)
- mail order bride (1)
- Mars bahis (2)
- Matadorbet (1)
- minimiri.comsitesi apr (3)
- Mobile App Development (771)
- Mostbet Russia (1)
- New Post (1)
- News (1)
- PB_TOPsitesi apr (1)
- PBsitesi_may (1)
- Pusulabet (1)
- redmirepool.bizsitesi apr (2)
- redmirepoolsitesi_may (1)
- Reference & Education, College (1)
- Reference & Education, Sociology (1)
- Rokusitesi apr (1)
- Sober living (6)
- Society, Divorce (1)
- Software development (7)
- Superbetin (1)
- Tempobet_next (1)
- thelongeststride.comsitesi apr (1)
- tipobet-turkiyesitesi apr (1)
- Ultrabet (1)
- Uncategorized (1)
- Игра (2)
- казино (1)
- Криптовалюты (1)
- Новости Криптовалют (1)
- Финтех (7)
- Форекс Брокеры (9)
- Форекс обучение (2)