我正在尝试制作一个用于日志记录的扩展功能。我想将
Any
作为参数发送并获取其名称。但找不到如何获取 Any
类的名称。有什么想法吗?
fun MainActivity.log(claz: Objects,any: Any){
Log.d("Main", claz.name + any.toString())
}
使用
yourClassInstance::class.simpleName
:
fun MainActivity.log(claz: Objects, any: Any){
Log.d("Main", "${claz::class.simpleName} ${any::class.simpleName}")
}
您可以使用 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 是反射包的一部分。因此,我假设它在一些或所有调用中使用反射。
这意味着如果权限被拒绝,您可能会收到 SecurityException。我在 try.kotlinlang.org 上测试了大部分内容,当使用
KClass#qualifiedName
和 KClass#simpleName
时,我在主方法中得到了带有 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
代替。 Any 与 Object 大致相同。
这意味着你的课程可能如下所示:
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.
}
}
}
我需要类似的东西来将原始 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
}
}
println(any::class.simpleName)
println(any::class.qualifiedName)
println(any::class.name)
println(any::class.javaObjectType.name)
println(any::class.javaObjectType.canonicalName)
println(any::class.javaObjectType.simpleName)
println(any::class.javaObjectType.typeName)
println(any.javaClass.simpleName)
println(any.javaClass.canonicalName)
println(any.javaClass.typeName)
println(any.javaClass.name)
println(any::class.java.simpleName)
println(any::class.java.typeName)
println(any::class.java.name)
println(any::class.java.canonicalName)