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

?

+3


source to share


2 answers


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.

+5


source


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

...
+1


source







All Articles