是否在运行时更改了声明/引用类型?

时间:2013-06-15 06:03:10

标签: java casting runtime

首先,让我清楚我所宣称的类型是什么意思。 假设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.强烈认为,在运行时,仅仅检查演员表,但实际上并没有改变声明的类型。

2 个答案:

答案 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。