jvm kotlin反射获取字段列表

pwuypxnk  于 2022-11-07  发布在  Kotlin
关注(0)|答案(9)|浏览(185)

在Kotlin中是否有java reflection foo.getClass().getFields()的等价物?我发现只有在知道字段名称时才能访问字段,但我希望以通用的方式处理字段。

piv4azn7

piv4azn71#

你是想要“backing field”中的字段还是“properties”中的字段......Kotlin实际上只有属性。你可以使用以下方法为某个类获取这些属性:

MyTest::class.memberProperties

// or 

MyTest::class.declaredMemberProperties

在Java Class<T>中,使用kotlin扩展属性获取KotlinKClass<T>,您可以从中继续:

someClassOfMine.javaClass.kotlin.memberProperties

这需要将kotlin-reflect依赖项添加到构建和类路径中。
对于属性背后的秘密支持字段,请使用Java反射,风险自负。

cczfrluj

cczfrluj2#

现在很容易与Kotlinv1.1,你可以使用以下方法来获得kotlin中的字段

val fields = MyClass.javaClass.kotlin.members

其中MyClass是您选择的类。
要使用此功能,您需要在gradle构建文件中包含kotlin-reflect,如下所示

compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

此外,如果您需要java字段,也可以直接从javaClass中获取字段(在某些情况下很有用,因为这些字段覆盖的范围略有不同)

val fields = MyClass.javaClass.declaredFields
41ik7eoe

41ik7eoe3#

简单的回答
在您构建.gradle(应用程序)文件时

implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version")

然后呢

val fields = YourClass::class.declaredMemberProperties
for (i in fields){
    Log.e("Fields ===", i.name)
}

干杯!!!

c9x0cxw0

c9x0cxw04#

你不能在Kotlin中这样做,但是在java中有一个肮脏的不可靠的方法来做到这一点。你可以使用java反射。就像这样:

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

让我们来测试一下:

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)

结果:

Fields: anotherVar, emptyClass, emptyTrait, contant, $kotlinClass
anotherVar: null
anotherVar: 10

工作正常)

bvn4nwqk

bvn4nwqk5#

  • Kotlin* 中有一个方法,它不需要在项目中添加新的依赖项即可工作:

假设一个名为Mine的自定义类

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

名为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
  }    
}

在声明一个Mine示例并对其进行测试之后。

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

aamkag616#

如果您希望属性的顺序与使用Kotlin-reflect声明的顺序相同:MyClass::class.primaryConstructor.parameters

hwamh0ep

hwamh0ep7#

我们可以使用memberProperties
示例:

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

// ...

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

u4dcyp6a8#

关于foo变量的示例,您可以通过以下方式获取其支持字段:

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

ix0qys7i9#

就像这样:

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

效果很好

相关问题