Kotlin:不能使用GenericTypeIndicator来调用Firebase数据库的getValue

时间:2017-03-02 04:36:54

标签: firebase firebase-realtime-database kotlin kotlin-interop

使用Kotlin处理Firebase数据库时,如果我使用List<String>,我似乎无法检索GenericTypeIndicator类型的值,如下所示:

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() {
    }
}

Kotlin来源(2)使用道格建议的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() {
    }
}

2 个答案:

答案 0 :(得分:18)

在Kotlin,

http://a:8080
http://b:8080

生成为(在Java中):

val ti = object : GenericTypeIndicator<List<String>>() {}

请注意通配符SyntethicClass ti = new SyntethicClass(); public final class SyntethicClass extends GenericTypeIndicator<List<? extends String>> {} ,而不仅仅是普通? extends String

请参阅https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#variant-generics了解相关信息。

为了防止这种情况,请使用String注释类型参数:

@JvmSuppressWildcards

这变得非常难看,但它确实有效。或者,根据Doug's answer使用val ti = object : GenericTypeIndicator<List<@JvmSuppressWildcards String>>() {}

答案 1 :(得分:3)

尝试更改此行:

snap.getValue(object : GenericTypeIndicator<List<String>>() {})

对此:

snap.getValue(object : GenericTypeIndicator<ArrayList<String>>() {})

它对我有用,但我不知道为什么。