我试图向上转换一个对象。但在运行时,对象的类仍然是一个派生类。
Derived drv = new Derived();
Base base = (Base) drv;
System.out.println("Class : " + base.getClass());
//prints -> Class : class packagename.Derived
那为什么类属性没有改变呢?
我试图向上转换一个对象。但在运行时,对象的类仍然是一个派生类。
Derived drv = new Derived();
Base base = (Base) drv;
System.out.println("Class : " + base.getClass());
//prints -> Class : class packagename.Derived
那为什么类属性没有改变呢?
那么为什么类属性没有改变呢?
因为对象本身并没有改变,只是你对它的引用类型发生了变化。强制类型转换对对象本身没有任何影响。
在Java中,与其他一些语言(谢天谢地)不同的是,引用类型很大程度上不会影响你获取方法的哪个版本。例如,考虑这两个类(由2rs2ts提供 - 谢谢!):
class Base {
public Base() {}
public void foo() {
System.out.println("I'm the base!");
}
}
class Child extends Base {
public Child() {}
public void foo() {
System.out.println("I'm the child!");
}
}
这段代码:
Child x = new Child();
Base y = (Base) x;
y.foo();
……输出
我是孩子!
因为即使 y
的类型是 Base
,我们调用 foo
方法的 对象 是 Child
,所以会调用 Child#foo
。这里(再次感谢2rs2ts)提供了一个可以测试的示例。
尽管你调用的方法(getClass
)只能是 Object#getClass
,因为它是一个final
方法(子类不能覆盖),但这个概念对于多态来说非常重要,我认为这可能是你问题的核心。
引用类型的主要作用是确定您可以访问对象的哪些方面。例如,假设我们将 bar
添加到 Child
中:
class Child extends Base {
public Child() {}
public void foo() {
System.out.println("I'm the child!");
}
public void bar() {
System.out.println("I'm Child#bar");
}
}
这段代码无法编译:
Child x = new Child();
Base y = (Base) x;
y.bar(); // <=== Compilation error
因为Base
没有bar
方法,所以我们无法通过类型为Base
的引用访问对象的bar
方法。
在Java中,您无法更改实例的类型。您使用强制转换所做的只是从不同类型的变量引用它。
向上转型不会改变对象的类型。事实上,没有任何东西可以改变Java对象的类型。
这就是面向对象编程的核心:一个对象具有定义好的行为,不能被外部影响。