如何获得任何班级的名字?

时间:2018-11-18 09:21:23

标签: kotlin

我正在尝试为日志记录创建扩展功能。我想发送Any作为参数并获取其名称。但是找不到如何获取Any类的名称。有什么想法吗?

fun MainActivity.log(claz: Objects,any: Any){
    Log.d("Main", claz.name +  any.toString())
}

4 个答案:

答案 0 :(得分:2)

使用yourClassInstance::class.simpleName

fun MainActivity.log(claz: Objects, any: Any){
    Log.d("Main", "${claz::class.simpleName} ${any::class.simpleName}")
}

答案 1 :(得分:1)

O(n^3.log(n))

答案 2 :(得分:1)

您可以为此使用Class或KClass,但是在这种情况下,最好使用KClass。否则,您必须将.java添加到课程中,如Blue Jones所述。

我不确定您想要哪个 名称。请记住,可以有多个具有相同名称的JVM类。实例的Closeable可以是java.io.Closeable,也可以是自定义实现,如果您还出于某种实际原因使用的库也可以使用它。

考虑到这一点,在一些有效的用例中,您需要限定名称。限定名称与“常规”名称相同,不同之处在于它还包括软件包。考虑一个实例:

import java.io.Closeable;

fun main(ar: Array<String>){
    val closeable = Closeable::class
    println(closeable.simpleName)
    println(closeable.qualifiedName)
}

这将打印:

Closeable
java.io.Closeable

您必须选择要使用的哪个,这取决于您的使用。如果您也想要该软件包,请使用qualifiedName。否则,请使用simpleName

您显然不必通过ClassName::class来上课。您还可以在实例上执行相同操作,这意味着您可以执行any::class并使用它来获取名称。

因此,为了获得名称,请使用any::class.qualifiedName。如果只希望类名不包含包,请使用simpleName

值得注意的是,KClass是a part of the reflection package。因此,我认为它在一些或所有调用中都使用了反射。

这意味着如果权限被拒绝,则可以获取SecurityException。我在try.kotlinlang.org上测试了其中的大部分内容,并且在使用KClass#qualifiedNameKClass#simpleName时,main方法中的lambda出现了SecurityException。

使用::class.java修复了该问题。因此,如果遇到安全异常,请使用class.java。命名实际上是相同的。 simpleName在那儿,但是qualifiedName只是name。您选择哪一个取决于您,但是两者都可以。

因此您的代码将类似于以下任一代码:

println(any::class.qualifiedName) // Alternatively with simpleName
println(any::class.java.name) // Alternatively with simpleName

最后,我看到您在其中一个实例上叫toString()。这将返回合格的类名称,其后带有一个哈希。这也是一种选择,但是如果您不想散列,请使用Class或KClass。

此外,我看到您使用MainActivity.log作为函数。我真的不明白为什么。如果您有一个仅限于单个类的日志记录功能,请将其放在伴随对象中。在类本身内部声明扩展函数也是没有意义的,因为调用是相同的。由于您可以编辑该类,并且它是我们正在讨论的单个类,因此可以将其移至伴随对象(可选,将其设为私有)。

使用字符串模板可以使您的代码受益,我将在最后一个示例中添加它。这是为了确保空格正确。在您当前的代码中,没有添加任何空间。我也找不到Objects#getName(),因此我认为这是获取名称本身的另一种尝试。 但是: Objects类,假设它是java.util.Objects,则无法初始化。这是一个实用程序类。如果您的意思是java.lang.Object,请改用Any。任何都与对象大致相同。

这意味着您的班级可能看起来像这样:

class MainActivity : Activity() {
    ...
    companion object {
        fun log(claz: Object, any: Any){
            Log.d("Main", "${claz::class.java.name} ${any::class.qualifiedName}") // I'm mixing the calls here to show you that you can use either. You can of course pick which you use.
        }
    }
}

答案 3 :(得分:1)

我需要类似的东西来将原始json响应作为对象映射为对象,并设法使其像这样

val depositResponse = convertResponseToObject(response , DepositResponse ::class.java.name) as DepositResponse
val withdrawResponse = convertResponseToObject(response , WithdrawResponse ::class.java.name) as WithdrawResponse
fun convertResponseToObject(response: String?, type: String ): Any{
    try {
        when (type) {
            DepositResponse ::class.java.name -> 
                 return ObjectMapper().readValue(response, DepositResponse ::class.java)
            WithdrawResponse ::class.java.name -> 
                 return ObjectMapper().readValue(response, WithdrawResponse ::class.java)
            else -> throw Exception("Error Mapping the json response")
        }
    }catch(e:Exception){
        throw e
    }
}