2017-03-02 42 views
3

當使用科特林與火力地堡數據庫的工作,我似乎無法檢索List<String>類型的值,如果我用一個GenericTypeIndicator如下:科特林:不能使用GenericTypeIndicator調用火力地堡數據庫的的getValue

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

它產生從火力地堡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>>() {}) 

我猜它與類型reifying做的,所以我這樣做:

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); 
    } 
} 

科特林源(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所建議由Doug:

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

我遇到的Kotlin語法沒有問題。類型重用不是問題,因爲您正在使用運行時類型創建新對象,這有效地實現了與具體類型相同的功能。編輯:但我確實有這個問題與名單而不是Foo ..怪異。 –

回答

11

在科特林,

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

如(在Java中)被產生:

SyntethicClass ti = new SyntethicClass(); 

public final class SyntethicClass extends GenericTypeIndicator<List<? 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's answer使用ArrayList

+0

有趣的 - 感謝解開這個。 –

+1

非常感謝,這有所幫助。只有一個提示,對於Maps,通配符僅用於像dataSnapshot.getValue(object:GenericTypeIndicator >(){})的值' – damienix

+0

謝謝!我已經添加了一些typaliases,使其不那麼難看: 'typealias UsersMap = Map ' 'val userTypeIndicator = object:GenericTypeIndicator (){} – treelzebub

2

嘗試改變這一行:

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

向該:

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

它適用於我,但我不知道爲什麼。

+0

感謝您提供'ArrayList'。它在使用'ArrayList'時起作用。我試圖反編譯Java代碼,並且Kotlin的'List'和'ArrayList'版本(我編輯了我的問題,結果可以在上面看到)。看來'List '被轉換爲'List <?擴展String>',但'ArrayList '保持爲'ArrayList '。那麼這看起來像是一個Kotlin「問題」。 – yuku

+0

我找到了解決方案。我把它作爲答案。 – yuku