小编典典
我急着打这个,所以请原谅任何错别字(我会在有机会的时候再改那些错)。
我知道Fruit f = new Fruit()将是静态和动态类型的Fruit。
我认为您将术语static and dynamic类型与编译时类型和运行时类型混淆了(或者像在C
++中那样,当您将类型A的对象的地址分配给类型B的指针,而B是A的父类时。 )
除反射技巧外,Java中没有动态类型。一切都是在编译时静态键入的。对象在运行时的类型与其被编译为的对象相同。
发生的事情是,您将对象引用(a,b,c,f)与堆中实例化的实际对象(使用new。创建的任何对象)相混淆。
在Java中,f是对象引用,而不是对象本身。此外,的参考类型f为Fruit and sub-classes of it。new
Fruit()您分配给它的对象()恰好是类型Fruit。
现在,示例代码中的所有其他引用都是a类型的reference to A and sub-classes of it;b是类型reference to
B and sub-classes of it; 等等等
请记住这一点,因为它非常重要。
αa = f; 在编译时将为Alpha类型(静态),在运行时将为Fruit类型(动态)。
a是“对类型A和子类的引用”类型。f是“对水果和子类的引用”类型。
f指向的对象的类型为“水果”。当您说“ a = f”时,您并未将“ f”分配给“ a”。您说的是“现在将引用f当前所指的事物”。
那么,分配之后,a引用的是什么?分配时指向Fruit的对象引用类型的对象f。
请记住,a,b,g,f不是对象。它们是对由new操作员以一种或另一种方式创建的对象的引用或句柄。
诸如a,b或f之类的引用变量与使用创建的对象是不同的野兽new。但是恰好前者可以指向后者。
在运行时使用new创建的对象的类型与在编译时确定的对象的类型相同。
伽玛g = f; 在编译时将为Gamma类型(静态),在运行时将为Fruit类型(动态)。
同上。变量g是类型的对象引用reference to type Gamma and sub-
classes。在此分配中,g使其指向指向的同一对象f。该对象的类型是什么?编译时给出的结果是:Fruit。
但是我不知道其他两个答案。Beta b =
f是一个实例,其中同一超类的两个子类相互分配,因此我不确定在编译时它是Beta类型还是Alpha类型(静态)。
b是类型reference to type Beta and sub-classes of it。它在分配后指向的对象b =
f的类型为Fruit,即在编译时具有的类型。
对象引用a,b,g和f的类型在编译时确定。它们是静态类型的,在运行时不会更改。
创建的对象的类型new也在编译时确定。它们也是静态类型的,在运行时不会更改。
这些对象(填充对象引用a,b,g和f) 在运行时 指向,这取决于编译器是否发现语句有效。分配可以更改,但是与对象引用或对象本身是静态还是动态类型无关。
如果要清楚区分动态类型和静态类型,请考虑以下内容:
// Java, statically typed.
int x = 3;
x = 5; // good
x = "hi"; // compiler error
## Ruby, dynamically typed
x = 3 # ok
x = 5 # ok
x = "hi" # still ok
然后,在强类型语言和弱/鸭子类型语言(这两种语言都可以动态类型)之间进行区分。那里有许多关于此主题的文献。
希望能帮助到你。
2020-09-21