Kotlin:不能使用GenericTypeIndicator调用Firebase数据库的getValue
当使用Kotlin处理Firebase数据库时,如果我使用GenericTypeIndicator
,我似乎无法检索List<String>
类型的值,如下所示:
snap.getValue(object : GenericTypeIndicator<List<String>>() {})
它从Firebase SDK中产生一个例外如下:
com.google.firebase.database.DatabaseException: Generic wildcard types are not supported at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.android.gms.internal.zzbtg.zza(Unknown Source) at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
但是,如果我从Java调用它,如下所示:
snap.getValue(new GenericTypeIndicator<List<String>>() {})
我猜测它与类型通用有关,所以我这样做了:
inline fun <reified T> genericType() = object: GenericTypeIndicator<T>() {} val stringListIndicator = genericType<List<String>>() snap.getValue(stringListIndicator)
但同样的例外发生。
为什么这样?
编辑:我试图使用jadx-0.6.1反编译Java和Kotlin版本。
Java源码:
public class Randommmm { private static final GenericTypeIndicator<List<String>> ti = new GenericTypeIndicator<List<String>>() { }; public static List<String> x(DataSnapshot snap) { return snap.getValue(ti); } }
反编译:
public class Randommmm { private static final GenericTypeIndicator<List<String>> ti = new C12761(); static class C12761 extends GenericTypeIndicator<List<String>> { C12761() { } } public static List<String> m48x(DataSnapshot snap) { return (List) snap.getValue(ti); } }
Kotlin来源(1):
object Randommmm { private val ti = object : GenericTypeIndicator<List<String>>() { } fun x(snap: DataSnapshot): List<String> { return snap.getValue(ti) } }
反编译:
public final class Randommmm { public static final Randommmm INSTANCE = null; private static final Randommmm$ti$1 ti = null; static class C12761 extends GenericTypeIndicator<List<String>> { C12761() { } } static { Randommmm randommmm = new Randommmm(); } private Randommmm() { INSTANCE = this; ti = new Randommmm$ti$1(); } @NotNull public final List<String> m48x(@NotNull DataSnapshot snap) { Intrinsics.checkParameterIsNotNull(snap, "snap"); Object value = snap.getValue(ti); Intrinsics.checkExpressionValueIsNotNull(value, "snap.getValue(ti)"); return (List) value; } } public final class Randommmm$ti$1 extends GenericTypeIndicator<List<? extends String>> { Randommmm$ti$1() { } }
(2)使用ArrayList
所建议的ArrayList
:
object Randommmm { private val ti = object : GenericTypeIndicator<ArrayList<String>>() { } fun x(snap: DataSnapshot): List<String> { return snap.getValue(ti) } }
反编译:
public final class Randommmm { public static final Randommmm INSTANCE = null; private static final Randommmm$ti$1 ti = null; static class C12761 extends GenericTypeIndicator<List<String>> { C12761() { } } static { Randommmm randommmm = new Randommmm(); } private Randommmm() { INSTANCE = this; ti = new Randommmm$ti$1(); } @NotNull public final List<String> m48x(@NotNull DataSnapshot snap) { Intrinsics.checkParameterIsNotNull(snap, "snap"); Object value = snap.getValue(ti); Intrinsics.checkExpressionValueIsNotNull(value, "snap.getValue(ti)"); return (List) value; } } public final class Randommmm$ti$1 extends GenericTypeIndicator<ArrayList<String>> { Randommmm$ti$1() { } }
在Kotlin,
val ti = object : GenericTypeIndicator<List<String>>() {}
生成为(在Java中):
SyntethicClass ti = new SyntethicClass(); public final class SyntethicClass extends GenericTypeIndicator<List<? extends String>> {}
注意通配符? extends String
? extends String
而不是简单的String
。
有关说明,请参阅https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#variant-generics 。
为了防止这种情况,使用@JvmSuppressWildcards
注释类型参数:
val ti = object : GenericTypeIndicator<List<@JvmSuppressWildcards String>>() {}
这变得超级丑陋,但它的作品。 或者,根据Doug的回答使用ArrayList
。
尝试改变这一行:
snap.getValue(object : GenericTypeIndicator<List<String>>() {})
对此:
snap.getValue(object : GenericTypeIndicator<ArrayList<String>>() {})
它适用于我,但我不知道为什么。