Kotlin use the same syntax as Java for Generics but generics behave a bit different. In Kotlin all generics type parameters must be specified (it does not default to “*”, even though Kotlin does have a “*” wildcard). Generics are invariant in Kotlin (like Java), making this assignment not allowed
val stringSet : HashSet<String>() stringSet.add("a") stringSet.add("b") var anySet : Set<Any> = stringSet //Not allowed
This is for a good reason, type-safety. If the above assignment was allowed, getting values from anySet would work fine because String is Any. However when values are added into anySet we run into trouble.
anySet.add(Date()) var totalLength = 0; for( str in stringSet ) { totalLength += str.length; //This will fail when date is reached }
However there are times where you know you will be just pulling values out of an object, for those cases Kotlin uses the out modifier.
fun printAll(set : Set<out Any>) { for( item in anySet ) { //item is Any println(item); } } printAll(stringSet)
Kotlin distinguishes between generic types passed into functions and generic types returned from functions (in/out modifiers). When you specify the generic type as out, all functions which reference that generic as an input parameter will be unavailable.
val anyOutSet : Set<out Any> = stringSet anyOutSet.add(Date()); //will not compile
Now back to the “*” wildcard.
Java
Set<*> => Set<Object>
Kotlin
Set<*> => Set<out Any?>
Java Set<Object> is similar to Set<out Any?> in Kotlin however it is not the same. As we know out generics limit the use to only functions which do not take the generic type as a parameter. Due to Kotlins enhanced type-safety there are times we have to think through the uses case a bit more than in Java.