2017-05-26 19 views
3

這工作得很好:防止科特林從迫使Java來看看一個通配符類型

class Wrapped<out T>(val value: T) 

open class Wrapper<T> { 
    fun wrap(map: T): Wrapped<T> = Wrapped(map) 
} 

class Wrapper2 : Wrapper<Map<String, String>>() 

val wrapped: Wrapped<Map<String, String>> = Wrapper2().wrap(mapOf()) 

但是,當我試圖從Java訪問Wrapper2.wrap,地圖回來了通配符類型:

Map<String, String> toWrap = new HashMap<>(); 
    Wrapped<Map<String, String>> result; 
    result = new Wrapper<Map<String, String>>().wrap(toWrap); // ok 
    result = new Wrapper2().wrap(toWrap); // NOT ok, returns Wrapped<Map<String, ? extends String>> 

我可以通過在Wrapper2中用明確類型重寫wrap來解決此問題。

爲什麼Wrapper2.wrap返回與Wrapper.wrap不同的類型?

回答

4

您可以使用泛型中的通配符作爲described in the Kotlin reference來抑制Kotlin,其中它描述了@JvmSuppressWildcards註釋(或該@JvmWildcard註釋的反轉)。

從文檔:

在另一方面,如果它們生成哪裏不需要通配符,我們可以使用@JvmSuppressWildcards

fun unboxBase(box: Box<@JvmSuppressWildcards Base>): Base = box.value 
// is translated to 
// Base unboxBase(Box<Base> box) { ... } 

注:@JvmSuppressWildcards都不能用只針對單個類型參數,而針對整個聲明(如函數或類),從而導致其中的所有通配符被抑制。

1

變化

class Wrapper2 : Wrapper<Map<String, String>>() 

class Wrapper2 : Wrapper<MutableMap<String, String>>() 

您將在科特林來源看,

public interface Map<K, out V> { 

而:

public interface MutableMap<K, V> : Map<K, V> { 

我相信out V是您得到? extends String的原因,請參閱Covariance下的Kotlin的仿製文檔,Google上的快速搜索應該會讓您更深入地瞭解covariance and contravariance in Java

+0

是的,這就是爲什麼Kotlin(不可變)'Map <>'表現的方式,謝謝! – gladed