Если Int не может быть нулевым, что означает значение null.asInstanceOf ?

В качестве теста я написал этот код:

object Ambig extends App { def f( x:Int ) { println("Int" ) } def f( x:String ) { println("String") } f( null.asInstanceOf[Int ] ) f( null.asInstanceOf[String] ) f(null) } 

Я ожидал получить ошибку при последнем вызове f (), сказав, что это было неоднозначно. Компилятор принял его и произвел этот вывод:

 Int String String 

Теперь я предполагаю, что это связано с тем, что Int не является AnyRef, поэтому единственной версией f, которая работает для f (null), является f (x: String). Но тогда, если Int не может быть нулевым, что означает значение null.asInstanceOf [Int]? Repl говорит, что это тип Int:

 scala> :type null.asInstanceOf[Int] Int 

но я действительно не вижу, как это работает. В конце концов, если я попытаюсь применить String к Int, все ад сломается:

 scala> "foo".asInstanceOf[Int] java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at scala.runtime.BoxesRunTime.unboxToInt(Unknown Source) ... 

Конечно, этого следует ожидать – «foo» нельзя превратить в Int. Но ни один из них не может быть нулевым, поэтому почему кастинг null в Int работает? Предположительно бокс в той или иной форме, но тип все еще Int, который не может быть нулевым …

Что мне не хватает?

Поведение отбрасывания null к Int зависит от контекста, в котором оно выполняется.

Прежде всего, если вы передаете null в Int , это на самом деле означает целое число в штучной упаковке, значение которого равно null . Если вы поместите выражение в контекст, где ожидаемым типом является Any (который переводится в Object за сценой, потому что в байт-коде JVM нет способа ссылаться на примитивный тип и ссылочный тип с той же ссылкой), то это значение больше не преобразуется – поэтому println(null.asInstanceOf[Int]) печатает null .

Однако, если вы используете это одно целое число в квадрате в контексте, где ожидается примитивный Int (Java int ), он будет преобразован в примитив, а null (как значение по умолчанию для ссылочных типов) преобразуется в 0 (по умолчанию значение для примитивных типов).

Если общий метод делает это, то, естественно, вы получите null обратно.

Однако, если этот метод специализирован, то его возвращаемым типом является Int (который в этом случае является примитивным целым), поэтому значение null: Any значение должно быть преобразовано в примитив, как и раньше.

Следовательно, запуск:

 object Test extends App { println(null.asInstanceOf[Int]) def printit(x: Int) = println(x) printit(null.asInstanceOf[Int]) def nullint[T] = null.asInstanceOf[T] println(nullint[Int]) def nullspecint[@specialized(Int) T] = null.asInstanceOf[T] println(nullspecint[Int]) } 

производит:

 null 0 null 0 

Вот что: asInstanceOf не имеет смысла. То, что этот метод делает, это сказать компилятору STOP MAKING SENSE и доверять тому, что вы говорите.

Теперь, если вы хотите знать, почему он возвращает 0, это потому, что asInstanceOf работает на AnyRef , а не на AnyVal . Когда применяется к AnyVal , AnyVal этого он будет использовать версию в штучной упаковке, а значение в null значении 0.

Похоже, он просто автоматически преобразует его в ноль:

 scala> null.asInstanceOf[Int] res0: Int = 0 

И, конечно, 0, в отличие от null, может быть Int .

Во-первых, мы все согласны с тем, что мы не можем назначить значение null для scala.Int как scala.Int в http://www.scala-lang.org/api/current/index.html#scala.Null

Во-вторых, почему, когда мы делаем println(null.asInstanceOf[Int]) , он дает null ?
Это происходит из-за реализации println. В конечном итоге он вызывает метод java String.valueOf , который

 return (obj == null) ? "null" : obj.toString(); 

Если вы выполните null.asInstanceOf[Int] == null в оболочке, он вернет true, но дает противоположное предупреждение о том, что «сравнение значений типов Int и Null с использованием` == ‘всегда будет давать false ». Я думаю, что это может быть проблемой в стирании типа scala.

Для выполнения println нужен только тип scala.Any, поэтому кастинг null.asInstanceOf[Int] самом деле еще не произошел. Поэтому нам просто нужно помнить, что когда вы присваиваете null.asInstanceOf[Int] значение Int, приведение происходит во время выполнения на основе семантики стирания Scala и присваивает ей значение 0.

Кстати, вы все равно можете делать af (null) без какой-либо ошибки компиляции, потому что scala делает неявное преобразование для вас

  null -> java.lang.Integer -> scala.Int 

Тем не менее, вы увидите, что он взрывается во время выполнения.

  • Какова мотивация присвоения Scala для оценки Unit вместо присвоенного значения?
  • Нет Json-сериализатора как JsObject для типа play.api.libs.json.JsObject
  • Полезность (как в практических приложениях) Currying vs Partial Application в Scala
  • Использование библиотеки Java с зарезервированными словами Scala
  • Когда следует выбирать Vector в Scala?
  • Макросы Scala: создание карты из полей classа в Scala
  • Spark / Scala: форвардная заливка с последним наблюдением
  • Запуск пользовательской задачи автоматически до / после стандартной задачи
  • Подписать CSR с помощью Bouncy Castle
  • Действительные символы идентификатора в Scala
  • Декартово произведение двух списков
  • Interesting Posts

    Как использовать .nextInt () и hasNextInt () в цикле while

    Разделить таблицу Excel на несколько слайдов PowerPoint

    Аутентифицированная среда равна нулю

    Ограничьте учетную запись пользователя, чтобы использовать только Internet Explorer (или Firefox) в Windows 7 Home Premium

    Snow Leopard скрывает полосу прокрутки в терминале?

    Как вы получаете строку из MemoryStream?

    Приложение Java EE Enterprise: выполните некоторые действия по развертыванию / запуску

    Как сравнить два богатых текстовых поля и выделить символы, которые были изменены?

    Резервное копирование и восстановление базы данных SQLite на SDCard

    Почему я не могу освободить объект?

    Что происходит с переменной float, когда% d используется в printf?

    Вызов метода с использованием тернарного оператора

    Обеспечивает ли источник питания столько энергии, сколько ему нужно?

    Как перечислить все поля в файле PDF в ITextSharp

    Должен ли я дефрагментировать накопитель SSD?

    Давайте будем гением компьютера.