对Java中的后期绑定/转换感到困惑

时间:2012-09-06 19:24:38

标签: java casting

class Person { void f() {} }
class Student extends Person { void f() {} }

所以当我执行以下代码时:

Person p = new Student();
((Person) p).f();

为什么在将变量转换为Person时调用Student类中的f()函数?我理解为什么f()函数仅在p.f()被调用时被调用,但我想我只是对演员的确是这样做了。

6 个答案:

答案 0 :(得分:1)

您始终可以将子类型转换为类型此类型的转换始终在java中允许,但因为实例属于子类型子类型方法将被执行。

您可以查看Here以获取更多信息 在Java中,有两种类型的引用变量:

  • 向下转换:如果您有引用子类型对象的引用变量,则可以将其指定给引用变量 亚型。您必须进行显式转换才能执行此操作,结果是 您可以使用此新引用访问子类型的成员 变量
  • 向上转换:您可以显式或隐式地将引用变量分配给超类型引用变量。这本身就是一种 安全操作,因为分配限制了访问 新变量的功能。

是的,您需要直接或间接实现接口,以便将类对象引用分配给接口类型。

答案 1 :(得分:1)

在调用方法时,由于ploymorphsim,它总是在对象类型上执行,而不是引用类型。

答案 2 :(得分:1)

这是面向对象:多态性的基石之一。你有各种各样的Person实体,每个实体都以自己的方式做f()!它是对象的实际实例,而不是你将它投射到f()的实例。

答案 3 :(得分:1)

同样的方法 - 学生中的方法 - 将被调用,无论你是否将学生转为一个人。

向上转换引用(从子类到超类)不起任何实际功能(实际上通常是内部的无操作)。另一方面,向下转发告诉JVM您认为超类属于指定的子类,如果不是,则会引发强制转换错误。

(我会给gefei指出上面的遗漏:演员ALSO告诉编译器类型,编译器使用这些信息知道对象(假设)有哪些方法和字段。这不是绝对必要的将Java程序编译为字节码,但它确实允许编译器进行通常的编译时有效性检查。)

答案 4 :(得分:0)

这里的预告无关紧要。如果存在,将始终调用重写的方法。

答案 5 :(得分:0)

你的例子中的演员完全没用。编译器知道p的类型为Person。更有趣的是缩小演员阵容:

Person p = getPerson();
if (p instanceof Student) {
    Student s = (Student) p;
    // do something Student-specific with s
}

在Java中强制转换引用类型 not 会改变对象的性质;它只告诉编译器可以对该对象做出什么假设。在运行时,对象的实际类型用于确定调用的方法。 (请注意,原始类型不是这样;将int强制转换为byte会更改数据。)