https://kotlinlang.org logo
Title
t

tschuchort

04/23/2019, 5:54 PM
Is
Foo<*>
in Kotlin equivalent to
Foo<?>
in Java?
:yes: 1
Note: star-projections are very much like Java's raw types, but safe.
s

starke

04/23/2019, 6:07 PM
safe as in type safe?
k

karelpeeters

04/23/2019, 6:07 PM
Yes, you aren't allowed to call any functions that would require you to know the type.
👍 1
t

tschuchort

04/23/2019, 6:10 PM
but you can. So they would be more like an unbounded wildcard wouldn't they?
k

karelpeeters

04/23/2019, 6:12 PM
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

tschuchort

04/23/2019, 6:20 PM
why do we need
*
at all when it seems to be equivalent to
in Nothing
?
s

streetsofboston

04/23/2019, 6:33 PM
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

tschuchort

04/23/2019, 6:37 PM
That works perfectly fine with
List<in Nothing>
as well. I don't see any difference between the two
s

streetsofboston

04/23/2019, 6:40 PM
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

Dias

04/23/2019, 6:41 PM
@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

tschuchort

04/23/2019, 6:58 PM
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

ilya.gorbunov

04/23/2019, 7:49 PM
*
-projection is equivalent to both
out U
and
in Nothing
, where
U
is the upper bound of the generic parameter
t

tschuchort

04/23/2019, 7:56 PM
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

streetsofboston

04/23/2019, 8:16 PM
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

tschuchort

04/23/2019, 9:15 PM
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

streetsofboston

04/23/2019, 9:23 PM
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