Prevent Kotlin to force Java to see the wildcard type
This works great:
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())
But when I try to access Wrapper2.wrap
from Java the Map returns with a wildcard type:
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>>
I can get around this by overriding wrap
in Wrapper2
with an explicit type.
Why Wrapper2.wrap
does it return a different type than Wrapper.wrap
?
source to share
You can suppress Kotlin with wildcards in generics as described in the Kotlin link where it describes annotation @JvmSuppressWildcards
(or vice versa @JvmWildcard
).
From the docs:
On the other hand, if we don't need wildcards where they are generated, we can use
@JvmSuppressWildcards
:
fun unboxBase(box: Box<@JvmSuppressWildcards Base>): Base = box.value // is translated to // Base unboxBase(Box<Base> box) { ... }
NOTE.
@JvmSuppressWildcards
can be used not only for individual type arguments, but for all declarations such as functions or classes, causing all wildcards within them to be suppressed.
source to share
Change
class Wrapper2 : Wrapper<Map<String, String>>()
to
class Wrapper2 : Wrapper<MutableMap<String, String>>()
You will see in the Kotlin source,
public interface Map<K, out V> {
then:
public interface MutableMap<K, V> : Map<K, V> {
I believe out V
- the reason you are getting ? extends String
see Covariance under the generics docs for Kotlin and a quick google search should give you a deeper understanding of covariance and contravariance in Java
source to share