防止Kotlin强制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返回一个通配符类型:

  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不同的类型?

您可以使用Kotlin参考中描述@JvmSuppressWildcards注释(或该@JvmSuppressWildcards注释的反向)中描述的泛型中的通配符来抑制Kotlin。

从文档:

另一方面,如果我们不需要生成通配符,我们可以使用@JvmSuppressWildcards

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

注意: @JvmSuppressWildcards可以用在单独的类型参数上,还可以用在整个声明上,比如函数或类,这样就可以禁止其中的所有通配符。

更改

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

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

你会看到在Kotlin的来源,

 public interface Map<K, out V> { 

然而:

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

我相信out V是你得到的原因? extends String ? extends String ,请参阅Kotlin的泛型文档中的Covariance ,在Google上快速搜索应该会让您更深入地了解Java中的协变和逆变 。