Разница между «*» и «Any» в дженериках Kotlin

107

Я не уверен, что полностью понимаю разницу между SomeGeneric<*>и SomeGeneric<Any>. Я думаю, что *представляет собой что-либо (подстановочный знак) и Anyпредставляет объект, от которого наследуются ВСЕ объекты. Кажется, они должны быть такими же, но так ли?

Колесо Строитель
источник

Ответы:

159

Может быть полезно думать о проекции звезды как о способе представления не просто любого типа, а некоторого фиксированного типа, который вы точно не знаете.

Например, тип MutableList<*>представляет собой список чего-либо (вы не знаете, что именно). Так что если вы попытаетесь что-то добавить в этот список, у вас ничего не получится. Это может быть список Strings, или список Ints, или список чего-то еще. Компилятор вообще не разрешает помещать какой-либо объект в этот список, потому что он не может проверить, принимает ли список объекты этого типа. Однако, если вы попытаетесь получить элемент из такого списка, вы обязательно получите объект типа Any?, потому что все объекты в Kotlin наследуются от Any.

Из комментария asco ниже:

Кроме того, List<*>может содержать объекты любого типа, но только этого типа, поэтому он может содержать строки (но только строки), а List<Any> может содержать строки, целые числа и еще много чего, все в одном списке.

Александр Удалов
источник
83
Хороший ответ, для некоторых может быть полезно добавить, что List <*> может содержать объекты любого типа, но только этого типа, поэтому он может содержать строки (но только строки), а List <Any> может содержать строки и целые числа и еще много чего, все в одном списке.
fweigl
1
Вот интересная статья с подобным объяснением: typealias.com/guides/star-projections-and-how-they-work
крокодилий
28

В контексте, как я думаю, вы подразумеваете, SomeGeneric<*>эквивалентно SomeGeneric<out Any?>. Эквивалент Java - SomeGeneric<? extends Object>.

Синтаксис называется «звездные проекции». Вот официальные документы: https://kotlinlang.org/docs/reference/generics.html#star-projection

воддан
источник