首先,让我清楚我所宣称的类型是什么意思。 假设SuperBoss是Boss类的超类。
SuperBoss mrBond = new Boss();
SuperBoss是声明的类型,Boss是实际类型。
就我个人而言,我认为由于以下运行时异常,声明的类型在运行时被更改:
SuperBoss mrWayne = new SuperBoss();
((Boss)mrWayne).randomMethod();
//Exception: java.lang.ClassCastException: SuperBoss cannot be cast to Boss
我知道这可能看似微不足道,但我将在下个季度进行辅导,而且我不想教学生错误的事情。而本季度我的教授和她的助手在这个问题上并不认同。我的教授认为,对于单个语句,转换确实完全改变了运行时声明的类型。 T.A.强烈认为,在运行时,仅仅检查演员表,但实际上并没有改变声明的类型。
答案 0 :(得分:1)
我的教授认为,对于单个语句,转换确实在运行时完全改变了声明的类型。 T.A.强烈认为,在运行时,仅仅会检查演员表,但实际上并没有改变声明的类型。
事实上,我认为在某种意义上它们都是正确的。他们所说的话并没有矛盾......如果你能弄清楚他们究竟在说些什么。
声明的mrWayne
类型不会改变。声明的((Boss) mrWayne)
类型确实“改变”。或者至少,它与声明的mrWayne
类型不同。
这里的真正问题是某人正在使用草率的术语......人们正在互相谈论。
好的考虑这个例子:
public class Test {
public static void method(Object t) {
system.out.println("Its an object");
}
public static void method(Test t) {
system.out.println("Its a test");
}
public static void main(String[] args) {
Test t = new Test();
method(t);
method((Object) t);
}
}
这应输出:
Its a test
Its an object
为什么呢?因为(Object) t
的声明的类型是Object
...而不是Test
。并且声明类型(不是运行时类型)确定method
的两个重载中的哪一个用于特定调用。
请参阅?
这一切都取决于你在说什么。声明的变量类型或表达式的声明类型。
答案 1 :(得分:1)
“声明”类型是您向编译器声明的类型。编译程序后它不会改变。
“运行时”类型是分配给变量的实际对象的类型。它仅在分配新对象时更改。 (它永远不会改变给定的对象,没有对象实例可以改变它的类。)
转换桥接两者:它检查运行时类型,然后允许您声明该类型。如果检查失败,程序将中止(使用RuntimeException)。如果您有比编译器更多的类型信息,则需要执行此操作。然后,您可以向编译器“声明”相关对象确实是“Boss”,而不仅仅是“SuperBoss”(这是编译器可以保证的最佳方式)。
我的教授认为,对于单个语句,转换确实在运行时完全改变了声明的类型。
Casting在编译时“声明”一个更具体的类型。但它还包括运行时检查以确保安全。
The T.A.强烈认为,在运行时,仅仅检查演员表,但实际上并没有改变声明的类型。
检查在运行时发生,但在代码中使用强制转换允许您在编译时进行更具体的类型声明。
((Boss)mrWayne).randomMethod();
发生了两件事:
编译时间:你声明这是一个Boss。否则你无法调用该方法。
运行时:JVM检查该对象是否真的是Boss。