Greetings community!
Let’s say in my Android project I have a data class:
data class Foo(
val a: Int,
val b: String,
)
Now if I use kotlin reflection to access its fields, all goes well. The console will print:
a PUBLIC Success(1)
b PUBLIC Success(b)
However, this only works for debug build. If building the app in release mode, things will change, and I found that, all members became PRIVATE, which caused a reflection access failure.
a PRIVATE Failure(kotlin.reflect.full.IllegalCallableAccessException: java.lang.IllegalAccessException: Class java.lang.Class<kotlin.reflect.jvm.internal.calls.CallerImpl$FieldGetter> cannot access private final field int org.example.kotlinreflection.Foo.a of class java.lang.Class<org.example.kotlinreflection.Foo>)
b PRIVATE Failure(kotlin.reflect.full.IllegalCallableAccessException: java.lang.IllegalAccessException: Class java.lang.Class<kotlin.reflect.jvm.internal.calls.CallerImpl$FieldGetter> cannot access private final field java.lang.String org.example.kotlinreflection.Foo.b of class java.lang.Class<org.example.kotlinreflection.Foo>)
In release build, Foo
’s public fields become Kotlin’s private properties, and getters and setters are generated correspondingly. Directly accessing the private members is forbidden.
This makes me confused. If we want the fields be private, we can just add the private
modifier; fields declared as public
(though in Kotlin public
can be omitted) becoming private implicitly after release build, kinda unintuitive and comfusing for me. Just say, Kotlin-specific reflection methods (methods under K*
) can’t access member values in a plain Kotlin data class?
Note class
(instead of data class
) has the same thing (members becoming private after release build). Btw the annotation @JvmField
works, and that’s just because it tells the compiler treat them as vanilla Java members - don’t touch them!
I’m fairly new to Kotlin. Maybe I missed something about Kotlin fields vs properties vs reflection?
Any idea? Thanks.