3

首先,让我清楚我所说的声明类型是什么意思。假设 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

我知道这可能看起来微不足道,但我将在下个季度进行辅导,我不想教学生错误的东西。本季度我的教授和她的助理在这个问题上意见不一。我的教授认为,强制转换确实会在运行时完全改变单个语句的声明类型。TA 坚信在运行时,转换只是被检查,但实际上并没有改变声明的类型。

4

2 回答 2

3

我的教授认为,强制转换确实会在运行时完全改变单个语句的声明类型。TA 坚信在运行时,转换只是被检查,但实际上并没有改变声明的类型。

事实上,我认为他们在某种意义上都是对的。他们所说的没有矛盾……如果你能弄清楚他们实际上在说什么。

声明的类型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) tObject......不是Test。并且它是声明的类型(不是运行时类型)决定了两个重载中的哪method一个用于特定的调用。

看?

这完全取决于在说什么。变量的声明类型,或表达式的声明类型。

于 2013-06-15T06:07:34.223 回答
1

“声明的”类型是您向编译器声明的类型。程序编译后它不会改变。

“运行时”类型是分配给变量的实际对象的类型。它仅在您分配新对象时发生变化。(对于给定的对象,它永远不会改变,没有对象实例可以改变它的类)。

强制转换将两者联系起来:它检查运行时类型,然后允许您声明该类型。如果检查失败,程序将中止(带有 RuntimeException)。当您拥有比编译器更多的类型信息时,您需要这样做。然后,您可以向编译器“声明”所讨论的对象确实是“Boss”,而不仅仅是“SuperBoss”(这是编译器可以保证的最好的)。

我的教授认为,强制转换确实会在运行时完全改变单个语句的声明类型。

强制转换在编译时“声明”了一个更具体的类型。但它还包括运行时检查以确保安全。

TA 坚信在运行时,转换只是被检查,但实际上并没有改变声明的类型。

检查发生在运行时,但在代码中进行强制转换允许您在编译时进行更具体的类型声明。

((Boss)mrWayne).randomMethod(); 

发生两件事:

  • 编译时间:你声明这是一个Boss。否则你无法调用该方法。

  • 运行时:JVM 检查该对象是否真的是 Boss。

于 2013-06-15T06:08:37.337 回答