Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin, how to retrieve field value via reflection

So I have hundreds of fields in a couple of classes and I'd like to write some methods on them where they automatically println each field and its corresponding value

At the moment I have this:

inner class Version(val profile: Profile) {

    @JvmField val MINOR_VERSION = glGetInteger(GL_MINOR_VERSION)

    fun write(file: File? = null) {
        //file.printWriter().use { out -> out.pri }
        this::class.java.fields.forEach {
            println(it.isAccessible)
            println(it.getInt(it)) }
    }
}

But this is what I get:

false
Exception in thread "main" java.lang.IllegalArgumentException: Can not set final int field uno.caps.Caps$Version.MINOR_VERSION to java.lang.reflect.Field
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeQualifiedIntegerFieldAccessorImpl.getInt(UnsafeQualifiedIntegerFieldAccessorImpl.java:58)

Any idea?

like image 469
elect Avatar asked Jul 10 '17 15:07

elect


People also ask

How do you find the value of field in a reflection?

Field. get(Object obj) method returns the value of the field represented by this Field, on the specified object. The value is automatically wrapped in an object if it has a primitive type.

What is :: means in Kotlin?

:: converts a Kotlin function into a lambda. this translates to MyClass(x, y) in Kotlin.


2 Answers

Instead of using Java fields and Java reflection code, you can also use Kotlin properties and Kotlin reflection classes:

class Reflector {
    val Foo = 1;

    fun printFields() {
        this::class.memberProperties.forEach {
            if (it.visibility == KVisibility.PUBLIC) {
                println(it.name)
                println(it.getter.call(this))
            }
        }
    }
}
like image 152
BladeCoder Avatar answered Oct 13 '22 07:10

BladeCoder


It seems that you are passing the Field variable it as a parameter getInt whereas the parameter should be the object the field belongs to this:

From the Javadoc for Field.getInt(Object obj):

obj - the object to extract the int value from

Perhaps this is what you meant to do:

class Reflector {
    @JvmField val Foo = 1;

    fun printFields() {
        this.javaClass.fields.forEach {
            println(it.isAccessible)
            println(it.getInt(this))
        }
    }
}

fun main(args : Array<String>) {
    Reflector().printFields()
}
like image 1
Frank Wilson Avatar answered Oct 13 '22 06:10

Frank Wilson