简体   繁体   English

强制转换会在运行时更改声明/引用类型吗?

[英]Does casting change the declared/reference type at run-time?

First, let me be clear about what I mean by the declared type. 首先,让我弄清楚声明类型的含义。 Assume SuperBoss is a superclass of the class Boss. 假设SuperBoss是Boss类的超类。

SuperBoss mrBond = new Boss();

SuperBoss is the declared type, and Boss is the actual type. SuperBoss是声明的类型,而Boss是实际的类型。

Personally, I think the declared type is changed at run-time due to the following run-time exception: 我个人认为,由于以下运行时异常,因此声明的类型在运行时已更改:

SuperBoss mrWayne = new SuperBoss();
((Boss)mrWayne).randomMethod(); 

//Exception: java.lang.ClassCastException: SuperBoss cannot be cast to Boss

I know this may seem trivial, but I'm going to be tutoring next quarter, and I don't want to teach the students the wrong thing. 我知道这看似微不足道,但我将在下个季度进行补习,也不想教给学生错误的事情。 And my professor and her assistant this quarter did not agree with each other on this subject. 我的教授和她的助手本季度在这个问题上彼此不同意。 My professor believes that casting does indeed completely change the declared type at run-time for a single statement. 我的教授认为,强制转换确实可以在运行时完全更改单个语句的声明类型。 The TA strongly believed that at run-time, the cast is merely checked, but doesn't actually change the declared type. TA坚信,在运行时仅对强制类型转换进行检查,但实际上并未更改声明的类型。

My professor believes that casting does indeed completely change the declared type at run-time for a single statement. 我的教授认为,强制转换确实可以在运行时完全更改单个语句的声明类型。 The TA strongly believed that at run-time, the cast is merely checked, but doesn't actually change the declared type. TA坚信,在运行时仅对强制类型转换进行检查,但实际上并未更改声明的类型。

In fact, I think that they are both right in a sense. 实际上,我认为它们在某种意义上都是正确的。 There is no contradiction in what they are saying ... if you can figure out what they are actually saying. 他们说的话没有矛盾……如果您能弄清楚他们在说什么。

The declared type of mrWayne does not change. mrWayne的声明类型不会更改。 The declared type of ((Boss) mrWayne) does "change". ((Boss) mrWayne)的声明类型执行“更改”。 Or at least, it is different to the declared type of mrWayne . 或至少与声明的mrWayne类型不同。

The real problem here is that someone is using sloppy terminology ... and people are talking past each other. 真正的问题是, 有人在使用草率的术语……人们彼此交谈。


OK consider this example: 好,请考虑以下示例:

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);
   }
}

This should output: 这应该输出:

Its a test
Its an object

Why? 为什么? Because the declared type of (Object) t is Object ... not Test . 因为(Object) t声明类型是Object ... not Test And it is the declared type (not the runtime type) that determines which of the two overloads of method is used for a particular call. 它是声明的类型(不是运行时类型),它确定method的两个重载中的哪个用于特定调用。

See? 看到?

It all depends on what you are talking about. 这一切都取决于你在说什么 The declared type of the variable, or the declared type of the expression. 变量的声明类型,或表达式的声明类型。

The "declared" type is what you declared to the compiler. “声明的”类型是您向编译器声明的类型。 It does not change after the program is compiled. 程序编译后,它不会更改。

The "runtime" type is the type of the actual object assigned to a variable. “运行时”类型是分配给变量的实际对象的类型。 It only changes when you assign a new object. 仅当您分配新对象时,它才会更改。 (It never changes for a given object, no object instance can change its class). (对于给定的对象,它永远不会更改,任何对象实例都不能更改其类)。

The cast bridges the two: It checks the runtime type and then allows you to declare that type. 强制转换在两者之间架起了桥梁:它检查运行时类型,然后允许您声明该类型。 If the check failed, the program will abort (with a RuntimeException). 如果检查失败,程序将中止(带有RuntimeException)。 You need to do this when you have more type information then the compiler. 当您拥有比编译器更多的类型信息时,需要执行此操作。 You can then "declare" to the compiler that the object in question is indeed a "Boss", and not just a "SuperBoss" (which is the best the compiler could otherwise guarantee). 然后,您可以向编译器“声明”所涉及的对象确实是“ Boss”,而不仅仅是“ SuperBoss”(这是编译器可以保证的最好的)。

My professor believes that casting does indeed completely change the declared type at run-time for a single statement. 我的教授认为,强制转换确实可以在运行时完全更改单个语句的声明类型。

Casting "declares" a more specific type at compile-time. 强制转换在编译时“声明”一个更具体的类型。 But it also includes a runtime check to make this safe. 但是它还包括运行时检查以确保安全。

The TA strongly believed that at run-time, the cast is merely checked, but doesn't actually change the declared type. TA坚信,在运行时仅对强制类型转换进行检查,但实际上并未更改声明的类型。

The check happens at runtime, but having the cast in your code allows you are more specific type declaration at compile-time. 该检查在运行时进行,但是将代码强制转换为代码可以使您在编译时进行更具体的类型声明。

((Boss)mrWayne).randomMethod(); 

Two things happen: 发生两件事:

  • compile time: You declare that this is a Boss. 编译时间:您声明这是Boss。 Otherwise you couldn't call the method. 否则您将无法调用该方法。

  • run time: The JVM checks if that object really is a Boss. 运行时:JVM检查该对象是否真的是Boss。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM