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

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

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

为什么f()将变量转换为 Person 时调用 Student 类中的函数?我理解为什么f()在它只是 时调用该函数p.f(),但我想我只是对演员表的确切作用感到困惑。

4

6 回答 6

1

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

您可以在此处查看更多信息在 Java 中有两种类型的引用变量转换:

  • Downcasting:如果你有一个引用变量引用一个子类型对象,你可以将它分配给子类型的一个引用变量。您必须进行显式强制转换才能做到这一点,结果是您可以使用这个新的引用变量访问子类型的成员。
  • Upcasting:您可以显式或隐式地将引用变量分配给超类型引用变量。这是一个本质上安全的操作,因为赋值限制了新变量的访问能力。

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

于 2012-09-06T19:26:24.747 回答
1

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

于 2012-09-06T19:28:02.583 回答
1

这是面向对象的基石之一:多态性。您有各种 Person 实体,每个实体都以自己的方式执行 f()!它是对象的实际实例,而不是 f() 所转换的对象。

于 2012-09-06T19:28:07.857 回答
1

无论您是否将 Student 转换为 Person,都会调用相同的方法——Student 中的方法。

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

(我会感谢 gefei 指出上面的一个遗漏:强制转换 ALSO 告诉编译器类型,编译器使用此信息来了解对象(假定)具有哪些方法和字段。这对于编译Java 程序到字节码,但它确实允许编译器进行通常的编译时有效性检查。)

于 2012-09-06T19:29:25.500 回答
0

向上转型在这里是无关紧要的。如果存在,将始终调用被覆盖的方法。

于 2012-09-06T19:28:21.460 回答
0

你的例子中的演员是完全没用的。编译器知道它p是 type Person。更有趣的是缩小范围:

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

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

于 2012-09-06T19:30:56.830 回答