21

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?

1

3 Answers 3

52

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))
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

How about java class?
hey @elect Please check my solution: stackoverflow.com/a/56115232/2939453
Is this still correct? I don't see memberProperties but only members. Kotlin version 1.5.20.
@DamnVegetables needs implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
1

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()
}

Comments

1

Note that you should first add the following dependency:

dependencies {
    implementation(kotlin("reflect"))
    // ...
}

Also, to get fields of a static Java class or fields that are static, use staticProperties instead of memeberProperties:

// R.raw is a static class in Android and its fields are also static
for (property in R.raw::class.staticProperties) {
    println(property.name)
    println(property.get())
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.