Причина первого результата в том, что метод getClass
имеет следующую подпись в Java
public final Class<?> getClass()
который наследует Скала. Хотя мы знаем, что если мы вызовем getClass
для ссылки типа T, подпись может быть
public final Class<? extends T> getClass()
компилятор не делает. Вы могли бы представить какое-то расширение языка для предоставления специального типа, представляющего статический тип получателя, который позволил бы
public final Class<? extends Receiver> getClass()
или какой-то специальный регистр в компиляторе для getClass
. На самом деле кажется, что Snoracle Java действительно особый случай getClass
, но я не уверен, что это требуется спецификацией языка Java. Однако, если у вас есть ссылка на какой-то конкретный статический тип T, нет никаких причин, по которым вы не можете сделать эквивалент T.class
(java) или classOf[T]
(scala). Другими словами, такое расширение не принесло бы большей выразительной силы, но усложнило бы реализацию языка.
Что касается «приведения времени компиляции» и «статического» приведения, то здесь действительно нет никакой разницы. Было бы правильно, чтобы компилятор десугар x.asInstanceOf[T]
до classOf[T].cast(x)
.
Любой язык с подтипами будет иметь возможность того, что статически известный тип ссылки менее специфичен, чем тип значения, к которому он относится. Языки со статическими системами типов, которые не имеют подтипов, обычно не имеют понятия о типах времени выполнения, поскольку существует только один фактический тип, который населяет данное имя типа. В этих языках типы стираются во время выполнения, почти так же, как параметры типа стираются в JVM.
Надеюсь, это поможет вам понять статические типы ссылок по сравнению с типом значений во время выполнения.