防止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中的协变和逆变 。