我试图向上转换一个对象。但是在运行时对象类仍然作为派生类。
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
is Base
,我们调用的对象foo
也是 a Child
,所以Child#foo
会被调用。这里(再次由2rs2ts提供)是一个关于 ideone 的示例。
Child#foo
尽管经历了引用,但我们得到的事实Base
对于多态性至关重要。
现在,恰好你调用的方法 ( 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
方法,所以我们不能通过bar
type 的引用访问对象的方法Base
。
您不能在 Java 中更改实例的类型。您对演员表所做的只是从不同类型的变量中引用它。
upcast 不会改变对象的类型。事实上,NOTHING 不会改变 Java 对象的类型。
这就是 OO 编程的核心:对象具有不受外部影响的已定义行为。