编译时类型和运行时类型之间存在差异的原因是什么?

soc*_*soc 5 java types programming-languages scala language-design

在Scala/Java(〜在JVM上),有一些较小的情况,行为不同,如:

/* "Dynamic" cast */
"".getClass.cast("Foo")
//res0: Any = Foo

/* "Static" cast */
classOf[String].cast("Foo")
//res1: String = Foo

/* "Compile time cast" */
"Foo".asInstanceOf[String]
res2: String = Foo
Run Code Online (Sandbox Code Playgroud)

在哪种语言中,编译时间和运行时间之间的差距更大,是否有语言设计POV的原因为什么这可能是一件"好事"?

走向另一个方向:是否存在(静态类型)语言,编译时和运行时类型之间没有任何差异?

Geo*_*edy 6

第一个结果的原因是该getClass方法在Java中具有以下签名

public final Class<?> getClass()
Run Code Online (Sandbox Code Playgroud)

Scala继承了哪些.虽然我们知道如果我们调用getClass类型为T的引用,签名就可以了

public final Class<? extends T> getClass()
Run Code Online (Sandbox Code Playgroud)

编译器没有.您可以想象一些语言扩展,以提供一种特殊类型,表示将启用的接收器的静态类型

public final Class<? extends Receiver> getClass()
Run Code Online (Sandbox Code Playgroud)

或编译器中的某种特殊外壳getClass.事实上,Snoracle Java确实是特殊情况,getClass但我不确定Java语言规范是否需要它.但是,如果您有某个特定静态类型T的引用,则没有理由不能执行等效T.class(java)或classOf[T](scala).换句话说,这样的扩展不会带来更大的表达能力,但会使语言的实现复杂化.

至于"编译时间演员"与"静态'演员阵容",那里真的没什么区别.这将是正确的编译器desugar x.asInstanceOf[T]classOf[T].cast(x).

任何具有子类型的语言都有可能静态已知类型的引用不如它所引用的值的类型具体.具有静态类型系统但没有子类型的语言通常没有运行时类型的概念,因为只有一个实际类型存在于给定类型名称中.在这些语言中,类型在运行时被擦除,这与在JVM上擦除类型参数的方式非常相似.

我希望这与运行时类型的值相比,有助于理解静态类型的引用.