在 Java 中,anObject
可以有一个运行时类型(它被创建为什么)和一个转换类型(您将它转换为的类型)。
我想知道这些类型的正确名称是什么。例如
class A {
}
class B extends A {
}
A a = new B();
a 被创建为 aB
但是它被声明为 a A
。指代a
使用每个视角的类型的正确方法是什么?
在 Java 中,anObject
可以有一个运行时类型(它被创建为什么)和一个转换类型(您将它转换为的类型)。
我想知道这些类型的正确名称是什么。例如
class A {
}
class B extends A {
}
A a = new B();
a 被创建为 aB
但是它被声明为 a A
。指代a
使用每个视角的类型的正确方法是什么?
我认为区分对象(在执行时存在,并且仅具有其执行时类型)和具有编译时类型的表达式(例如变量)很重要。
所以在这种情况下:
A a = new B();
a
是一个变量,类型为A
。它在执行时的值是对类型对象的引用B
。
Java 语言规范对对象的类型使用“运行时类”(例如,为了覆盖,如第 15.12.4.4 节中所述)。在其他地方,我认为它只是将“类型”用于表达式的类型,即编译时类型。
Java 语言规范谈到了变量的声明类型,javadocgetClass()
谈到了对象的运行时类。
请注意,Java 中没有运行时类型。List<String>
并且List<Integer>
是不同的类型,但它们的实例共享相同的运行时类。
在这种情况下,A
是引用类型,B
而是实例类型
我想说你区分变量/引用的类型和对象的类型。在这种情况下
A a = new B();
变量/引用将是类型A
,但对象类型B
。
变量的类型a
是A
。没有改变,因为它是一个参考。它碰巧引用了一个类型为 的对象B
。当您B
通过A
引用引用该对象时,您只能将其视为 type A
。
您可以稍后将其转换为更具体的类型
B b = (B)a;
并使用该B
对象上的方法。
您正在寻找的术语是表观类型和实际类型。
A a = new B();
表观类型是 A ,因为编译器只知道对象是 A 类型。因此,此时您不能引用任何 B 特定方法。
实际类型是 B。您可以强制转换对象(即更改其表观类型)以访问 B 特定方法。
例如,
如果表达式的类型是引用类型,那么被引用对象的类,甚至值是否是对对象的引用而不是 null,在编译时不一定是已知的。在 Java 编程语言中的一些地方,引用对象的实际类以无法从表达式类型推断的方式影响程序执行......
[剪辑]
可以使用类型为引用类型 的表达式来测试该表达式的运行时值
instanceof
是否引用了对象的类
因此,将上述语言应用于
A a = new B();
我们可能会说类似
表达式的静态类型
a
是A
,尽管存储的值a
是对运行时类对象的引用B
。
就个人而言,我以以下方式解释这两个概念(但请注意,我不确定其正确性):
要确定a
您可以使用哪个类的对象:
/*The java.lang.Object.getClass() method returns the runtime class of an object*/
System.out.println("a is object of: "+a.getClass());