I was reading a kotlin documentation about differences between Java and Kotlin here https://kotlinlang.org/docs/reference/comparison-to-java.html. It was stated there that Kotlin does not have wildcard-types. However after reading carefully through the documentation of generics I have found information about star-projection and honestly I can't see the difference. Can somebody explain to me how this
List<?> list;
differs from this
lateinit var list: MutableList<*>
Star Projection: Sometimes you want to say that you know nothing about the type argument, but still want to use it in a safe way. The safe way here is to define such a projection of the generic type, that every concrete instantiation of that generic type would be a subtype of that projection.
When we define a collection with "*", it should contain the object of only that type. There should not be any mix and match between the data types inside a collection. If we use "Any", we can mix and match the data types, which means we can have multiple data types in a collection.
Wildcards in Java are basically the question marks which we use in generic programming, it basically represents the unknown type. We use Java Wildcard widely in situations such as in a type of parameter, local variable, or field and also as a return type.
Due to extensive capture conversion, in most places, compiler treats wildcards as if they are type variables. Therefore indeed programmer can replace wildcard with type variables in such places, a sort of manual capture conversion.
Note: In Kotlin a star projection MutableList<*> combines both out Any? and in Nothing projections, and the latter means that you cannot pass anything at all to the methods where the type is unknown (Nothing is the type that has no value). in Java and Kotlin.
? extends T — Wildcard with an upper bound T meaning: Only types that are subtypes of T are all allowed ? super T — Wildcard with a lower bound meaning: Only types that are supertypes of T are allowed only I hope Java wildcards are pretty much clear to you. Invariant — Where two objects are not equal. This might not be clear with just a definition.
One way in which Kotlin can be faster than Java is inline functions. With inline functions, code using higher-order functions such as filter or map can be compiled to simple loop-based bytecode that doesn't create any objects or use any virtual calls (unlike Java code that uses the same type of functions).
In Kotlin, There’s a solution for the same, which is declaration-site variance. In which we annotate the type parameter of the Class/Interface to make sure that the object is only returned and not consumed. This is done by defining the type as out (variance annotation).
Probably what it means is that Kotlin doesn't have wildcards in the same form as they are present in Java. Instead, Kotlin uses a different concept of mixed-site variance, which adds an option to specify the variance at declaration-site, that is something you cannot do with Java wildcards.
As to the star-projection, it is actually almost equivalent to an unbounded Java wildcard. However, there is at least one difference related to the Kotlin type system.
When you have a List<?>
, the type is unknown to Java, but all Java referential types are nullable, and therefore you can safely pass a null
as an argument of the unknown type, e.g. list.add(null)
.
In Kotlin that is not true, a star projection MutableList<*>
combines both out Any?
and in Nothing
projections, and the latter means that you cannot pass anything at all to the methods where the type is unknown (Nothing
is the type that has no value).
The same can be said of the out-projections: while you can pass a null
as a Java bounded wildcard type ? extends T
, you cannot do the same with Kotlin out T
projection.
And the exact equivalent of the Java unbounded wildcard is <in Nothing?>
, because it lets you pass a null
as an argument of the unknown type (Nothing?
is Nothing
∪ { null
}, this is the type that has only null
value).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With