Is `Foo<*>` in Kotlin equivalent to `Foo<...
# announcements
t
Is
Foo<*>
in Kotlin equivalent to
Foo<?>
in Java?
👌 1
Note: star-projections are very much like Java's raw types, but safe.
s
safe as in type safe?
k
Yes, you aren't allowed to call any functions that would require you to know the type.
👍 1
t
but you can. So they would be more like an unbounded wildcard wouldn't they?
k
Yeah that was a vague formulation, it's explained more concretely here: https://stackoverflow.com/questions/45520368/java-wildcard-types-vs-kotlin-star-projection
👍 1
😮 1
t
why do we need
*
at all when it seems to be equivalent to
in Nothing
?
s
E.g. this would allow a function with a parameter of type
list: List<*>
to still call
list.size
. Your function just needs to know it’s a list. It is not interested in what the list contains. And
*
is much less typing that
in Nothing
🙂
t
That works perfectly fine with
List<in Nothing>
as well. I don't see any difference between the two
s
val list: List<in Nothing>
does not compile, because a list is defined as
List<out T>
. But
val list: List<*>
works fine.
For
MutableList
, both
in Nothing
and
*
work, because
MutableList<T>
is invariant.
d
@tschuchort you are misusing Nothing, Nothing suppose to represent a value that doesn’t exist, like return type of the function that always throws, or loops forever
t
So if I wanted to convert between Kotlin and Java I'd have to check what declaration-site variance it has? If
Foo
comes from Java or Kotlin and is invariant then
Foo<?>
is equivalent to
Foo<in Nothing?>
. But what if it comes from Kotlin and has
in
or
out
variance?
i
*
-projection is equivalent to both
out U
and
in Nothing
, where
U
is the upper bound of the generic parameter
t
But how exactly is that mapped to wildcards in Java? When I make a function in Java:
void foo(Foo<?> f)
and one in Kotlin
fun bar(f: Foo<*>)
then the IDE shows that both are of type
(Foo<*>) -> Unit
(in a Kotlin file) but the Java one accepts null and the Kotlin one doesn't
s
But this is not because of generics… the java version’s
f
parameter accepts a
Foo<*>!
type because it comes from java (note the
!
), which accepts
null
as valid values. The
f
parameter of the kotlin version accepts a
Foo<*>
type, which is non-nullable
t
So no fancy conversion takes place? Every
Foo<?>
is directly converted to
Foo<*>!
? Why not, when it would be possible to encode the nullability?
s
Every type
T
from java is converted to
T!
when used in Kotlin. The
!
is denoting a platform type: https://kotlinlang.org/docs/reference/java-interop.html#notation-for-platform-types If you want to enforce nullable, non-nullable from Java, you should use the appropriate annotations in Java (if you have that option): https://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations