Kotlin 数组的具体化内联函数

Kotlin 数组的具体化内联函数,kotlin,Kotlin,在Kotlin中是否可以编写一个具有具体化类型的内联函数,该函数可以返回不同类型的数组?我会这样想: inline fun <reified E> getArray(key: String, defValue: Array<E>): Array<E>? { return when(defValue) { is Array<Int> -> // ... is Array<String?> -&

在Kotlin中是否可以编写一个具有具体化类型的内联函数,该函数可以返回不同类型的
数组
?我会这样想:

inline fun <reified E> getArray(key: String, defValue: Array<E>): Array<E>? {
    return when(defValue) {
        is Array<Int> -> // ...
        is Array<String?> -> // ...
        else // ...
    }
}
fun intArray(size: Int): Array<Int> = Array(size) {i -> 0}
fun stringArray(size: Int): Array<String?> = Array(size) {i -> null}

val strings: Array<Int> = getArray(KEY_INTS, intArray(0))
val strings: Array<String> = getArray(KEY_STRINGS, stringArray(0))
inline-fun-getArray(key:String,defValue:Array):数组?{
返回时间(defValue){
是数组->/。。。
是数组->/。。。
else/。。。
}
}
我想这样称呼它:

inline fun <reified E> getArray(key: String, defValue: Array<E>): Array<E>? {
    return when(defValue) {
        is Array<Int> -> // ...
        is Array<String?> -> // ...
        else // ...
    }
}
fun intArray(size: Int): Array<Int> = Array(size) {i -> 0}
fun stringArray(size: Int): Array<String?> = Array(size) {i -> null}

val strings: Array<Int> = getArray(KEY_INTS, intArray(0))
val strings: Array<String> = getArray(KEY_STRINGS, stringArray(0))
fun intArray(size:Int):数组=数组(size){i->0}
数组(大小:Int):数组=数组(大小){i->null}
val strings:Array=getArray(KEY_INTS,intArray(0))
val strings:Array=getArray(KEY_strings,stringArray(0))
但由此我得到了一个错误:

找不到已擦除类型的实例的检查


明确回答问题-您可以通过检查
E
类来使用它:

inline fun <reified E: Any> getArrayInline(key: String, defValue: Array<E>): Array<E>? {
    return when(E::class) {
        Int::class -> arrayOf(1, 2, 3)
        String::class -> arrayOf("a", "b", "c")
        else -> throw IllegalArgumentException("Invalid class: ${E::class.qualifiedName}")
    } as Array<E>
}
简单对吧?但一旦你查看生成的字节码,它就不那么好了。为了便于阅读,将Kotlin字节码反编译回Java:

public static final void testArrayInline() {
  String var1 = "key";
  Object[] defValue$iv = new Integer[0];
  KClass var3 = Reflection.getOrCreateKotlinClass(Integer.class);
  Object var10000;
  if (Intrinsics.areEqual(var3, Reflection.getOrCreateKotlinClass(Integer.TYPE))) {
     var10000 = new Integer[]{1, 2, 3};
  } else {
     if (!Intrinsics.areEqual(var3, Reflection.getOrCreateKotlinClass(String.class))) {
        throw (Throwable)(new IllegalArgumentException("Invalid class: " + Reflection.getOrCreateKotlinClass(Integer.class).getQualifiedName()));
     }

     var10000 = new String[]{"a", "b", "c"};
  }

  Integer[] test = (Integer[])((Object[])var10000);
  String var7 = "key2";
  Object[] defValue$iv = new String[0];
  KClass var4 = Reflection.getOrCreateKotlinClass(String.class);
  if (Intrinsics.areEqual(var4, Reflection.getOrCreateKotlinClass(Integer.TYPE))) {
     var10000 = new Integer[]{1, 2, 3};
  } else {
     if (!Intrinsics.areEqual(var4, Reflection.getOrCreateKotlinClass(String.class))) {
        throw (Throwable)(new IllegalArgumentException("Invalid class: " + Reflection.getOrCreateKotlinClass(String.class).getQualifiedName()));
     }

     var10000 = new String[]{"a", "b", "c"};
  }

  String[] test2 = (String[])((Object[])var10000);
}
考虑到函数只被调用了两次,在“when”块中有两个案例,它是相当大的。而且它甚至没有做任何有用的事情-您已经可以看到
if
案例的结果


正确的方法-将每种类型声明为单独的非内联函数:

fun getArray(key: String, defValue: Array<Int>) : Array<Int>{
    return arrayOf(1, 2, 3)
}

fun getArray(key: String, defValue: Array<String>) : Array<String>{
    return arrayOf("a", "b", "c")
}
public static final void testArray() {
  String var3 = "key";
  Integer[] var4 = new Integer[0];
  getArray(var3, var4);
  var3 = "key2";
  String[] var5 = new String[0];
  getArray(var3, var5);
}

明确回答问题-您可以通过检查
E
类来使用它:

inline fun <reified E: Any> getArrayInline(key: String, defValue: Array<E>): Array<E>? {
    return when(E::class) {
        Int::class -> arrayOf(1, 2, 3)
        String::class -> arrayOf("a", "b", "c")
        else -> throw IllegalArgumentException("Invalid class: ${E::class.qualifiedName}")
    } as Array<E>
}
简单对吧?但一旦你查看生成的字节码,它就不那么好了。为了便于阅读,将Kotlin字节码反编译回Java:

public static final void testArrayInline() {
  String var1 = "key";
  Object[] defValue$iv = new Integer[0];
  KClass var3 = Reflection.getOrCreateKotlinClass(Integer.class);
  Object var10000;
  if (Intrinsics.areEqual(var3, Reflection.getOrCreateKotlinClass(Integer.TYPE))) {
     var10000 = new Integer[]{1, 2, 3};
  } else {
     if (!Intrinsics.areEqual(var3, Reflection.getOrCreateKotlinClass(String.class))) {
        throw (Throwable)(new IllegalArgumentException("Invalid class: " + Reflection.getOrCreateKotlinClass(Integer.class).getQualifiedName()));
     }

     var10000 = new String[]{"a", "b", "c"};
  }

  Integer[] test = (Integer[])((Object[])var10000);
  String var7 = "key2";
  Object[] defValue$iv = new String[0];
  KClass var4 = Reflection.getOrCreateKotlinClass(String.class);
  if (Intrinsics.areEqual(var4, Reflection.getOrCreateKotlinClass(Integer.TYPE))) {
     var10000 = new Integer[]{1, 2, 3};
  } else {
     if (!Intrinsics.areEqual(var4, Reflection.getOrCreateKotlinClass(String.class))) {
        throw (Throwable)(new IllegalArgumentException("Invalid class: " + Reflection.getOrCreateKotlinClass(String.class).getQualifiedName()));
     }

     var10000 = new String[]{"a", "b", "c"};
  }

  String[] test2 = (String[])((Object[])var10000);
}
考虑到函数只被调用了两次,在“when”块中有两个案例,它是相当大的。而且它甚至没有做任何有用的事情-您已经可以看到
if
案例的结果


正确的方法-将每种类型声明为单独的非内联函数:

fun getArray(key: String, defValue: Array<Int>) : Array<Int>{
    return arrayOf(1, 2, 3)
}

fun getArray(key: String, defValue: Array<String>) : Array<String>{
    return arrayOf("a", "b", "c")
}
public static final void testArray() {
  String var3 = "key";
  Integer[] var4 = new Integer[0];
  getArray(var3, var4);
  var3 = "key2";
  String[] var5 = new String[0];
  getArray(var3, var5);
}

如果处理的类型有限,则应该考虑将该方法拆分为具有不同返回类型的倍数。内联巨大的switch语句会生成大量垃圾字节码。由于数组元素类型为E,因此可以检查类型E::class,而不是defValue@ErwinBolwidt你是说像E::class==Int::class之类的东西,或者我应该怎么做?你能详细解释一下吗?对不起,我是Kotlin新手,在java的限制下仍在思考……如果您处理的类型有限,您应该考虑将此方法分割成具有不同返回类型的倍数。内联巨大的switch语句会生成大量垃圾字节码。由于数组元素类型为E,因此可以检查类型E::class,而不是defValue@ErwinBolwidt你是说像E::class==Int::class之类的东西,或者我应该怎么做?你能详细解释一下吗?很抱歉,我是Kotlin的新手,仍然在思考Java的局限性……感谢您的回答。如果要使
defValue
参数为空,您有什么建议?如果我调用
getArray(“…”,null)
它将导致
重载解析歧义。那么我真的必须使用不同的方法名吗?@Cilenco
null
在这种情况下是不明确的,编译器无法解析要调用哪个方法。您必须将其强制转换为所需的可空类型,例如
getArray(“…”,null as Array?
。感谢您的回答。如果要使
defValue
参数为空,您有什么建议?如果我调用
getArray(“…”,null)
它将导致
重载解析歧义。那么我真的必须使用不同的方法名吗?@Cilenco
null
在这种情况下是不明确的,编译器无法解析要调用哪个方法。您必须将其强制转换为所需的可空类型,例如
getArray(“…”,null as Array?