Операторы с нулевым значением, допустимые в общем классе?

У Kotlin есть прекрасные возможности ( ?. И !!. ), обрабатывающие типы с нулевым значением. Но это меня просто поглаживает – что, если вы не знаете, имеете ли вы дело с типом с нулевым или непустым значением? Что делать, если у вас есть универсальный класс MyClass<T> , тогда у вас есть только один тип T и все.

Предоставляет ли Kotlin «обнуляемые» операторы, применяемые к родовому типу (здесь), может ли тип быть допустимым для NULL внутри класса (например, T? ), И что, если класс будет создан экземпляром с типом NULL – например MyClass<String?> . Будет ли он приводить к обнулению типа nullable (например, указатель на указатель в C ++ – **std::string ) в типе MyClass ?

Я просто попробовал это в веб-демо .

 class MyClass<T>(val x: T) { fun foo() { println(x.toString()) } fun fooSave() { println(x?.toString()) } } fun main(args: Array<String>) { MyClass<String?>(null).fooSave() MyClass<String?>(null).foo() } 

Кажется, вы всегда можете применить нуль-безопасный оператор ?. , даже если тип не обязательно является нулевым.

С другой стороны, вы можете привязать параметр типового типа T к типу NULL, в моем случае String? , который на самом деле будет генерировать исключение NullPointerException, если вы передадите null .

Изменить . Поскольку задан вопрос, семантика общих типов без верхней границы изменилась. T теперь интерпретируется как T : Any? , Однако вышеприведенный код больше не разбивается. Причина в том, что вызов x.toString() вызовет функцию расширения Any?.toString() которая корректно обрабатывает null s.

Если мы изменим код следующим образом

 class MyClass<T : Any>(val x: T) { fun foo() { println(x.toString()) } fun fooSave() { println(x?.toString()) } } fun main(args: Array<String>) { MyClass<String?>(null).fooSave() MyClass<String?>(null).foo() } 

он теперь даже не компилируется, потому что мы не можем создать экземпляр T : Any со String? , Вызов x?.toString() также помечен предупреждением, говорящим, что безопасный вызов не нужен.