Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
kotlin.time.Duration和java反射 P> >我似乎遇到了java反射API交互的一个奇怪的问题(尤其是,看起来java反射不能确定代码返回类型为 koTLIN。时间。持续时间< /代码>。考虑下面的例子: @file:JvmName("Main") package org.test.kotlin.time.duration import java.lang.reflect.Proxy import kotlin.time.Duration import kotlin.time.ExperimentalTime import kotlin.time.seconds @ExperimentalTime interface I { fun getNullableDuration(): Duration? = 1.seconds fun getRange(): IntRange = 1..3 fun getDuration(): Duration = 1.seconds } class IC: I inline fun <reified T> T.sampleProxy(): T = sampleProxy(T::class.java) fun <T> sampleProxy(c: Class<T>): T { return c.cast(Proxy.newProxyInstance(c.classLoader, arrayOf(c)) { _, method, _ -> println("[proxy] ${method.declaringClass.name}::${method.name} return type is ${method.returnType}") when (method.name) { "getNullableDuration", "getDuration" -> 1.seconds "getRange" -> 0..1 else -> TODO("method ${method.name} isn't handled yet") } }) } fun main() { val v: I = IC() println("I::getNullableDuration() return type is ${v::getNullableDuration.returnType}") v.sampleProxy().getNullableDuration() println("I::getRange() return type is ${v::getRange.returnType}") v.sampleProxy().getRange() println("I::getDuration() return type is ${v::getDuration.returnType}") v.sampleProxy().getDuration() }_Java_Kotlin_Reflection - Fatal编程技术网

kotlin.time.Duration和java反射 P> >我似乎遇到了java反射API交互的一个奇怪的问题(尤其是,看起来java反射不能确定代码返回类型为 koTLIN。时间。持续时间< /代码>。考虑下面的例子: @file:JvmName("Main") package org.test.kotlin.time.duration import java.lang.reflect.Proxy import kotlin.time.Duration import kotlin.time.ExperimentalTime import kotlin.time.seconds @ExperimentalTime interface I { fun getNullableDuration(): Duration? = 1.seconds fun getRange(): IntRange = 1..3 fun getDuration(): Duration = 1.seconds } class IC: I inline fun <reified T> T.sampleProxy(): T = sampleProxy(T::class.java) fun <T> sampleProxy(c: Class<T>): T { return c.cast(Proxy.newProxyInstance(c.classLoader, arrayOf(c)) { _, method, _ -> println("[proxy] ${method.declaringClass.name}::${method.name} return type is ${method.returnType}") when (method.name) { "getNullableDuration", "getDuration" -> 1.seconds "getRange" -> 0..1 else -> TODO("method ${method.name} isn't handled yet") } }) } fun main() { val v: I = IC() println("I::getNullableDuration() return type is ${v::getNullableDuration.returnType}") v.sampleProxy().getNullableDuration() println("I::getRange() return type is ${v::getRange.returnType}") v.sampleProxy().getRange() println("I::getDuration() return type is ${v::getDuration.returnType}") v.sampleProxy().getDuration() }

kotlin.time.Duration和java反射 P> >我似乎遇到了java反射API交互的一个奇怪的问题(尤其是,看起来java反射不能确定代码返回类型为 koTLIN。时间。持续时间< /代码>。考虑下面的例子: @file:JvmName("Main") package org.test.kotlin.time.duration import java.lang.reflect.Proxy import kotlin.time.Duration import kotlin.time.ExperimentalTime import kotlin.time.seconds @ExperimentalTime interface I { fun getNullableDuration(): Duration? = 1.seconds fun getRange(): IntRange = 1..3 fun getDuration(): Duration = 1.seconds } class IC: I inline fun <reified T> T.sampleProxy(): T = sampleProxy(T::class.java) fun <T> sampleProxy(c: Class<T>): T { return c.cast(Proxy.newProxyInstance(c.classLoader, arrayOf(c)) { _, method, _ -> println("[proxy] ${method.declaringClass.name}::${method.name} return type is ${method.returnType}") when (method.name) { "getNullableDuration", "getDuration" -> 1.seconds "getRange" -> 0..1 else -> TODO("method ${method.name} isn't handled yet") } }) } fun main() { val v: I = IC() println("I::getNullableDuration() return type is ${v::getNullableDuration.returnType}") v.sampleProxy().getNullableDuration() println("I::getRange() return type is ${v::getRange.returnType}") v.sampleProxy().getRange() println("I::getDuration() return type is ${v::getDuration.returnType}") v.sampleProxy().getDuration() },java,kotlin,reflection,Java,Kotlin,Reflection,可以看到,在sampleProxy中,getNullableDuration()和getRange()的返回类型被正确地确定(kotlin.time.Duration?预期变成kotlin.time.Duration),而getDuration()突然变成一个返回double的方法,从该方法返回时从kotlin.time.Duration到double的转换失败,出现异常 问题的原因是什么?我如何解决它 我的环境: OpenJDK 11.0.6+10 科特林1.3.71 Linux/x86-6

可以看到,在
sampleProxy
中,
getNullableDuration()
getRange()
的返回类型被正确地确定(
kotlin.time.Duration?
预期变成
kotlin.time.Duration
),而
getDuration()
突然变成一个返回
double
的方法,从该方法返回时从kotlin.time.Duration到double的转换失败,出现异常

问题的原因是什么?我如何解决它

我的环境:

  • OpenJDK 11.0.6+10
  • 科特林1.3.71
  • Linux/x86-64
是一个双

这意味着:

  • Kotlin编译器将尽可能使用
    double
  • 如果不是包装器类型,则将改为使用
本节:

在生成的代码中,Kotlin编译器为每个内联类保留一个包装器。内联类实例在运行时可以表示为包装器或底层类型

Kotlin编译器更喜欢使用底层类型而不是包装器来生成最高效和优化的代码。但是,有时有必要保留包装器。根据经验,内联类作为另一种类型使用时会被装箱。

在提供的示例中:

  • getNullableDuration
    返回
    Duration?
    ,这意味着装箱值(参见Kotlin文档部分中的示例)
  • getDuration
    只返回
    Duration
    ,允许编译器使用底层类型
    double
    而不是包装器
  • “getNullableDuration”,“getDuration”->1.seconds
    返回一个包装器而不是底层类型,因为返回一个对象,不允许编译器使用底层类型
这就是抛出
ClassCastException
的原因。编译的
getDuration
方法返回一个
double
,但代理将始终返回
Duration

以下是
IC
反编译为Java时的样子:

公共最终类IC实现I{
@可空
公共持续时间getNullableDuration(){
返回I.DefaultImpls.getNullableDuration(此);
}
@NotNull
公共内部网getRange(){
返回I.DefaultImpls.getRange(此);
}
//这里是双人房
公共双getDuration(){
返回I.DefaultImpls.getDuration(此);
}
}
权变措施 最简单的方法是使用可为null的类型

另一种方法是为
getDuration
方法返回
double

when(method.name){
“getNullableDuration”->1.5秒
“getDuration”->1.0
“getRange”->0..1
else->TODO(“尚未处理方法${method.name}”)
}

请注意,时间api和
inline
类都是实验性的

I::getNullableDuration() return type is kotlin.time.Duration?
[proxy] org.test.kotlin.time.duration.I::getNullableDuration return type is class kotlin.time.Duration
I::getRange() return type is kotlin.ranges.IntRange
[proxy] org.test.kotlin.time.duration.I::getRange return type is class kotlin.ranges.IntRange
I::getDuration() return type is kotlin.time.Duration
[proxy] org.test.kotlin.time.duration.I::getDuration return type is double
Exception in thread "main" java.lang.ClassCastException: class kotlin.time.Duration cannot be cast to class java.lang.Double (kotlin.time.Duration is in unnamed module of loader 'app'; java.lang.Double is in module java.base of loader 'bootstrap')
    at com.sun.proxy.$Proxy2.getDuration(Unknown Source)
    at org.test.kotlin.time.duration.Main.main(main.kt:38)
    at org.test.kotlin.time.duration.Main.main(main.kt)

Process finished with exit code 1