简体   繁体   English

kotlin 反射获取字段列表

[英]kotlin reflection get list of fields

is there an equivalent for the java reflection foo.getClass().getFields() in Kotlin? Kotlin 中的 java 反射foo.getClass().getFields()是否有等效项? 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.我只能发现当我知道它的名字时我可以访问一个字段,但我想以通用方式处理字段。

Did you want fields as-in "backing field" or fields as in "properties" ... Kotlin really only has properties.您想要“支持字段”中的字段还是“属性”中的字段...... Kotlin 实际上只有属性。 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:从 Java Class<T> ,使用kotlin扩展属性获取 Kotlin KClass<T> ,您可以从中继续:

someClassOfMine.javaClass.kotlin.memberProperties

This requires the kotlin-reflect dependency as well to be added to your build and classpath.这还需要将kotlin-reflect依赖项添加到您的构建和类路径中。 You'll find many other useful things on KClass你会在KClass上找到许多其他有用的东西

For the secret backing fields behind a property, use Java reflection at your own risk.对于属性背后的秘密支持字段,请自担风险使用 Java 反射。

Very easy now with Kotlin v1.1, You can use the following method to get the fields in kotlin现在使用 Kotlin v1.1 非常容易,您可以使用以下方法获取 kotlin 中的字段

val fields = MyClass.javaClass.kotlin.members

Where MyClass is the class of your choice.其中 MyClass 是您选择的类。

In order to use this you need to have kotlin-reflect included in your gradle build file as below为了使用它,您需要将 kotlin-reflect 包含在您的 gradle 构建文件中,如下所示

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)此外,如果您需要 java 字段,也可以直接从 javaClass 获取字段(在某些情况下很有用,因为它们涵盖的范围略有不同)

val fields = MyClass.javaClass.declaredFields

You can't do this in Kotlin, but there is a dirty unreliable way to do this in java.你不能在 Kotlin 中做到这一点,但在 Java 中有一种肮脏不可靠的方法来做到这一点。 You can use java reflection.您可以使用Java反射。 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 )有用 )

There is a method in Kotlin that works without having to add a new dependency in a project: Kotlin中有一种方法无需在项目中添加新的依赖项即可工作:

Suppose a custom class called Mine假设一个名为Mine的自定义类

class Mine(var prop:String) {
    fun myMethod():Boolean {
        return true
    }
}

A new user function called isMethod一个名为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.在声明一个Mine实例并对其进行测试之后。

fun main() {
  var m = Mine("Paulo")  
  println(isMethod(m, "myMethod"))  // it prints true
  println(isMethod(m, "otherMethod"))  // it prints false
}

Simple answer简单的回答

In you build.gradle (app) file在你的 build.gradle (app) 文件中

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!!!干杯!!!

如果您希望按使用Kotlin-reflect<\/code>声明它们的顺序排列属性: MyClass::class.primaryConstructor.parameters<\/code>

"

We can use memberProperties .我们可以使用memberProperties

Example:例子:

class Color {
    val name: String
    val red: Int
    val green: Int
    val blue: Int
}

// ...

Color::class.memberProperties.size // returns 4

Regarding your example with a foo variable you may get its backing fields through:关于带有foo变量的示例,您可以通过以下方式获得其支持字段:

val fields: List<Field?> = foo::class.memberProperties.map { it.javaField }

like this:像这样:

  User::class.memberProperties.forEach { member ->
        log.i("${member.name} -> ${member.get(this)}")
    }

It works very well它运作良好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM