Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.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 使用反射调用具有默认参数值的函数_Kotlin_Kotlin Reflect - Fatal编程技术网

Kotlin 使用反射调用具有默认参数值的函数

Kotlin 使用反射调用具有默认参数值的函数,kotlin,kotlin-reflect,Kotlin,Kotlin Reflect,考虑一个接口: interface Foo { fun func(argWithDefault: String = "default") } 及其(最低限度)实施: class FooImpl() : Foo { override fun func(argWithDefault: String) { println(argWithDefault) } } 我也在尝试通过反射调用FooImpl上的func: val func = Foo::func va

考虑一个接口:

interface Foo {
    fun func(argWithDefault: String = "default")
}
及其(最低限度)实施:

class FooImpl() : Foo {
    override fun func(argWithDefault: String) {
        println(argWithDefault)
    }
}
我也在尝试通过反射调用
FooImpl
上的
func

val func = Foo::func
val instance = FooImpl()
func.callBy(mapOf(func.instanceParameter!! to instance))
但我有以下例外:

kotlin.reflect.jvm.internal.KotlinReflectionInternalError:此可调用项不支持默认调用:public abstract fun func(argWithDefault:kotlin.String=…):com.example.Foo中定义的kotlin.Unit[DeserializedSimpleFunctionDescriptor@2d7275fc]

Foo::func.parameters[1]。等选项
返回
true
,根据文档,
等选项
返回

如果此参数是可选的,并且在通过KCallable.callBy进行调用时可以忽略,则为true,否则为false


所以我想这应该是可能的;dr:这似乎是一个已知的问题:

我以前做过一些分析:

如果我们看一下Kotlin在这里实际生成的内容,就会发现为什么不再有任何默认值。
Foo的字节码

public abstract interface Foo {

  public abstract func(Ljava/lang/String;)V
    LOCALVARIABLE this LFoo; L0 L1 0
    LOCALVARIABLE argWithDefault Ljava/lang/String; L0 L1 1

  public final static INNERCLASS Foo$DefaultImpls Foo DefaultImpls
}


// ================Foo$DefaultImpls.class =================
  public static synthetic func$default(LFoo;Ljava/lang/String;ILjava/lang/Object;)V
    ALOAD 3
    IFNULL L0
    NEW java/lang/UnsupportedOperationException
    DUP
    LDC "Super calls with default arguments not supported in this target, function: func"
    INVOKESPECIAL java/lang/UnsupportedOperationException.<init> (Ljava/lang/String;)V
    ATHROW
   L0
    ILOAD 2
    ICONST_1
    IAND
    IFEQ L1
   L2
    LINENUMBER 2 L2
    LDC "default" // <--- here is our default value? but where are we? Foo$Defaults.func$default?
    ASTORE 1
   L1
    ALOAD 0
    ALOAD 1
    INVOKEINTERFACE Foo.func (Ljava/lang/String;)V (itf)
    RETURN
    MAXSTACK = 3
    MAXLOCALS = 4

  public final static INNERCLASS Foo$DefaultImpls Foo DefaultImpls
  // compiled from: Foo.kt
}
为了完整起见,我还创建了一个
Caller.kt
,其中只包含以下代码:

fun main() = FooImpl().func()
最后是字节码,也是我们的
DefaultImpls.func$default
-调用:

public final class CallerKt {


  public final static main()V
   L0
    LINENUMBER 1 L0
    NEW FooImpl
    DUP
    INVOKESPECIAL FooImpl.<init> ()V
    ACONST_NULL
    ICONST_1
    ACONST_NULL
    INVOKESTATIC Foo$DefaultImpls.func$default (LFoo;Ljava/lang/String;ILjava/lang/Object;)V // aha! here is our DefaultImpls.func$default!
    RETURN
   L1
    MAXSTACK = 4
    MAXLOCALS = 0
public final类CallerKt{
公共最终静态main()V
L0
1号线L0
新食品
重复
调用特殊的FooImpl
空的
ICONST_1
空的
INVOKESTATIC Foo$DefaultImpls.func$default(LFoo;Ljava/lang/String;ILjava/lang/Object;)V//aha!这是我们的DefaultImpls.func$default!
返回
L1
MAXSTACK=4
最大局部变量=0
因此,
DefaultImpls
只是由编译器生成并在需要时使用,
reflect
实用程序也可以(而且在我看来应该)反映这一事实……我添加了一个关于开放类的类似已知问题(它们也使用合成的
…$default
-函数)如果这个问题不能完全解决你的担忧,你可能想开辟一个新的领域

只是稍微处理了一下链接问题……实际上,如果使用
a::foo
而不是
B::foo
a
是开放类,
B
扩展
a
),那么那里的示例就可以工作了但是,由于
A
基本上与您的
Foo
-接口相似,因此该接口需要对此进行特殊处理

public final class CallerKt {


  public final static main()V
   L0
    LINENUMBER 1 L0
    NEW FooImpl
    DUP
    INVOKESPECIAL FooImpl.<init> ()V
    ACONST_NULL
    ICONST_1
    ACONST_NULL
    INVOKESTATIC Foo$DefaultImpls.func$default (LFoo;Ljava/lang/String;ILjava/lang/Object;)V // aha! here is our DefaultImpls.func$default!
    RETURN
   L1
    MAXSTACK = 4
    MAXLOCALS = 0