这很好用:
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>>
我可以通过使用显式类型覆盖wrap
中的Wrapper2
来解决此问题。
为什么Wrapper2.wrap
会返回与Wrapper.wrap
不同的类型?
答案 0 :(得分:6)
您可以使用通配符中的通配符来抑制Kotlin described in the Kotlin reference,其中它描述@JvmSuppressWildcards
注释(或@JvmWildcard
注释的反向)。
来自文档:
另一方面,如果我们不需要在生成它们的通配符,我们可以使用
@JvmSuppressWildcards
:fun unboxBase(box: Box<@JvmSuppressWildcards Base>): Base = box.value // is translated to // Base unboxBase(Box<Base> box) { ... }
注意:
@JvmSuppressWildcards
不仅可以用于单个类型参数,还可以用于整个声明,例如函数或类,从而使其中的所有通配符都被抑制。
答案 1 :(得分:1)
更改
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
的原因,请参阅Kotlin的仿制文档下的Covariance,快速搜索Google可以让您更深入地了解covariance and contravariance in Java。