Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Kotlin from forcing Java to see a wildcard type

Tags:

kotlin

This works fine:

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 comes back 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 work around this by overriding wrap in Wrapper2 with the explicit type.

Why does Wrapper2.wrap return a different type than Wrapper.wrap?

like image 272
gladed Avatar asked May 26 '17 20:05

gladed


2 Answers

You can suppress Kotlin using wildcards in generics as described in the Kotlin reference where it describes the @JvmSuppressWildcards annotation (or the reverse of that @JvmWildcard annotation).

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 on individual type arguments, but on entire declarations, such as functions or classes, causing all wildcards inside them to be suppressed.

like image 64
4 revs Avatar answered Nov 01 '22 01:11

4 revs


Change

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

to

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

You'll see in the Kotlin source,

public interface Map<K, out V> {

whereas:

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

I believe out V is the reason you're getting ? extends String, see Covariance under the generics docs for Kotlin and a quick search on Google should give you some more insight into covariance and contravariance in Java .

like image 36
Jan Vladimir Mostert Avatar answered Nov 01 '22 01:11

Jan Vladimir Mostert