Reputation: 321
is there an equivalent for the java reflection foo.getClass().getFields()
in Kotlin? I could only find that I can access a field when I know it's name, but I would like to handle fields in a generic way.
Upvotes: 32
Views: 46636
Reputation: 9373
Regarding your example with a foo
variable you may get its backing fields through:
val fields: List<Field?> = foo::class.memberProperties.map { it.javaField }
Upvotes: 0
Reputation: 158
We can use memberProperties
.
Example:
class Color {
val name: String
val red: Int
val green: Int
val blue: Int
}
// ...
Color::class.memberProperties.size // returns 4
Upvotes: 0
Reputation: 598
If you want the properties in the order they are declared using Kotlin-reflect
:
MyClass::class.primaryConstructor.parameters
Upvotes: 1
Reputation: 1574
Simple answer
In you build.gradle (app) file
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version")
And then
val fields = YourClass::class.declaredMemberProperties
for (i in fields){
Log.e("Fields ===", i.name)
}
Cheers!!!
Upvotes: 3
Reputation: 207
like this:
User::class.memberProperties.forEach { member ->
log.i("${member.name} -> ${member.get(this)}")
}
It works very well
Upvotes: -1
Reputation: 2659
There is a method in Kotlin that works without having to add a new dependency in a project:
Suppose a custom class called Mine
class Mine(var prop:String) {
fun myMethod():Boolean {
return true
}
}
A new user function called isMethod
fun isMethod(t:Any, s:String):Boolean {
try {
t.javaClass.getMethod(s) // or t::class.java.getMethod(s)
return true
} catch(e:Exception) {
return false
}
}
After one declares an Mine
instance and test it.
fun main() {
var m = Mine("Paulo")
println(isMethod(m, "myMethod")) // it prints true
println(isMethod(m, "otherMethod")) // it prints false
}
Upvotes: 2
Reputation: 2497
Very easy now with Kotlin v1.1, You can use the following method to get the fields in kotlin
val fields = MyClass.javaClass.kotlin.members
Where MyClass is the class of your choice.
In order to use this you need to have kotlin-reflect included in your gradle build file as below
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
Additionally, it is also possible to get the fields from the javaClass directly if you need java fields (useful in some cases as these cover a slightly different scope)
val fields = MyClass.javaClass.declaredFields
Upvotes: 5
Reputation: 85946
Did you want fields as-in "backing field" or fields as in "properties" ... Kotlin really only has properties. You can get these for some class using:
MyTest::class.memberProperties
// or
MyTest::class.declaredMemberProperties
And from a Java Class<T>
, use the kotlin
extension property to get the Kotlin KClass<T>
from which you can proceed:
someClassOfMine.javaClass.kotlin.memberProperties
This requires the kotlin-reflect
dependency as well to be added to your build and classpath. You'll find many other useful things on KClass
For the secret backing fields behind a property, use Java reflection at your own risk.
Upvotes: 24
Reputation: 10518
You can't do this in Kotlin, but there is a dirty unreliable way to do this in java. You can use java reflection. Like this:
public class TestClass {
trait EmptyTrait
class EmptyClass
public var anotherVar:Int? = null
public val contant:Float = 10f
private var emptyTrait:EmptyTrait? = null
val emptyClass:EmptyClass = EmptyClass()
public fun setVal(fieldName: String, value: Int) {
javaClass.getDeclaredField(fieldName).set(this, value);
}
public fun getFieldNames(): String {
return javaClass.getDeclaredFields().map{it.getName()}.join(", ")
}
}
Let's test it:
val t = TestClass()
Log.v("MainActivity", "Fields: " + t.getFieldNames())
Log.v("MainActivity", "anotherVar: " + t.anotherVar)
t.setVal("anotherVar", 10)
Log.v("MainActivity", "anotherVar: " + t.anotherVar)
Results:
Fields: anotherVar, emptyClass, emptyTrait, contant, $kotlinClass
anotherVar: null
anotherVar: 10
it works )
Upvotes: 2