Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin extension function access Java private field

I'd like to access Java's private field when using Kotlin extension function.

Suppose I have a Java class ABC. ABC has only one private field mPrivateField. I'd like to write an extension function in Kotlin which uses that field for whatever reason.

public class ABC {     private int mPrivateField;  } 

the Kotlin function would be:

private fun ABC.testExtFunc() {     val canIAccess = this.mPrivateField; } 

the error I'm getting is:

Cannot access 'mPrivateField': It is private in 'ABC'

Any way of getting around that limitation?

like image 594
kosiara - Bartosz Kosarzycki Avatar asked Jul 16 '17 17:07

kosiara - Bartosz Kosarzycki


People also ask

Can extension methods access private members Kotlin?

Now it's clear to see you cannot access private member of $receiver , since they're, well, private. If you really want to access that member, you could do so using reflection, but you'll lose all guarantees.

How do you access Kotlin extension functions in Java?

In Kotlin, you can easily call another function by just importing the same in the current Kotlin file where your main function is running.

What is the purpose of Kotlin extension function?

Extension functions are a cool Kotlin feature that help you develop Android apps. They provide the ability to add new functionality to classes without having to inherit from them or to use design patterns like Decorator.


2 Answers

First, you need to obtain a Field and enable it can be accessible in Kotlin, for example:

val field = ABC::class.java.getDeclaredField("mPrivateField")  field.isAccessible = true 

Then, you can read the field value as Int by Field#getInt from the instance of the declaring class, for example:

val it: ABC = TODO()  val value = field.getInt(it) 

Last, your extension method is looks like as below:

private inline fun ABC.testExtFunc():Int {     return javaClass.getDeclaredField("mPrivateField").let {         it.isAccessible = true         val value = it.getInt(this)         //todo         return@let value;     } } 
like image 161
holi-java Avatar answered Sep 19 '22 17:09

holi-java


That is not possible by design. Extension functions essentially resolve to static functions with the receiver as its first parameter. Thus, an extension function

fun String.foo() {   println(this) } 

compiles to something like:

public static void foo(String $receiver) {   System.out.println($receiver); } 

Now it's clear to see you cannot access private member of $receiver, since they're, well, private.

If you really want to access that member, you could do so using reflection, but you'll lose all guarantees.

like image 23
nhaarman Avatar answered Sep 22 '22 17:09

nhaarman