所以,我在Java中有这三个类。 当我运行程序时,我得到:
20,
15,
10,
我的问题是,为什么我会这样做而不是:
15,
20(不是public int getX();在B类中得到15 + 5 = 20?),
10
例如?
请你一步一步地向我解释一下这个程序到底发生了什么,因为我对输出(以及序列)非常困惑。
public class A {
private int x = 15;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public void printX() {
System.out.println(this.getX());
}
}
子:
public class B extends A {
private int x = 5;
@Override
public int getX() {
return super.getX() + x;
}
@Override
public void setX(int x) {
super.setX(x);
super.printX();
}
@Override
public void printX() {
System.out.println(super.getX());
}
}
和
public class C {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
答案 0 :(得分:1)
这是因为您将a
实例化为B
对象 - A a = new B()
。明确的a
类型是A
并不重要;它比实际类型B
更通用(抽象)(因为B
继承自A
),因此多态性在第一顺序中调用B
方法(更具体)。这同样适用于领域。
调用a.getX()
类B
对A
的{{1}}的引用,返回其getX()
(超类方法没有引用它的对象在这种情况下调用),然后添加15
(5
的{{1}}),结果为B
。
后续调用的行为方式类似。
答案 1 :(得分:0)
我已经给出了一个类似于你的问题的基本例子,你会得到你的答案。这是运行时多态
的概念 Inheritance
创建typecompatibility
。它允许超类引用引用子类的对象。 (反向不是真的)。
引用子类对象的超类引用只能用于访问子类的继承和overrridden
方法。使用超类的引用无法访问sub class
中新定义的成员。
class A
{
void f1()//this holds address of object of B
{
System.out.println("A f1");
}
void f2()
{
System.out.println("A f2");
}
}//A
class B extends A
{
void f3()//new method
{
System.out.println("B f3");
}
void f2()//this holds address of object of B
{
System.out.println("B f2 starts");
f3(); //this.f3()
System.out.println("B f2 ends ");
}
}//B
class TypeCmptbl
{
public static void main(String args[])
{
A ref; //reference of A
ref = new B();//Object of B
//ref.inherited() allowed
ref.f1();
//ref.overridden() allowed
ref.f2();
//ref.newMembersOfChild() not allowed
//ref.f3();
}//main
}
考虑声明
ref.f2();
这里ref是A类的引用,它有B类对象的地址f2()是一个重写方法。
当编译器检测到这样的语句时,它不会将函数调用与任何定义绑定。它只验证通话。
此类调用的绑定留给运行时环境。在程序运行时,系统识别对象的数据类型,并使用对象类提供的函数定义绑定函数调用。函数调用和函数定义之间的这种类型的绑定称为"runtime polymorphism"
。
答案 2 :(得分:0)
A a = new B();
因此a
的具体类型为B
。
System.out.println(a.getX());
您在类型B的对象上调用getX()。因此调用以下方法,因为a
的具体类型为B
,而B
已覆盖由A:
getX()
方法
public int getX() {
return super.getX() + x;
}
它添加了B的x(其值为5),结果为super.getX()
。 A中的此方法定义为
public int getX() {
return x;
}
所以它返回A的x
,它被初始化为15。
结果是5 + 15 = 20。
其余的可以用同样的方式解释。请记住,不能以多态方式访问字段。只有方法。因此,在A
的代码中,当您看到x
时,它始终意味着“字段x在A中的值”。在B
的代码中,当您看到x
时,它始终意味着“字段x在B中的值”。
答案 3 :(得分:0)
您的问题与java中的运行时多态性有关,即方法在运行时绑定,变量在编译时绑定
在你的例子中
public class C {
public static void main(String[] args) {
A a=new B();
System.out.println(a.getX());
a.setX(10);
a.printX();
}
}
// reference is of A but the object is of B, so at runtime JVM see that memory is of B so the B's method is called, this is runtime Polymorphism
答案 4 :(得分:0)
当调用以下语句时,将调用类B的getX()。
System.out.println(a.getX());
@Override
public int getX() {
return super.getX() + x; // this will add 15 from class A + 5 in this method.
}
the above statement displays 20
当调用以下语句时, a.setX(10);
@Override
public void setX(int x) {
super.setX(x); // observe this method, this prints 15
super.printX(); // this prints 10
}
// super.setX(X);它会调用
public void setX(int x) {
this.x=x; // 10 <--- 15 so 15 is displayed
}
这里this.x指的是通过a.setX(10)传递的值。
答案 5 :(得分:0)
当你说:
a a = new B();
它意味着A的对象用类B实例化。因此,在内存中,为对象'a'保留一个空格,其中包含B类(而不是A)的所有方法和属性。
因此,当执行第一个print语句时,它执行B类的getX()方法而不是A类的getX()方法。
对于对象'a'调用的其他方法,将调用类B的方法。
这也称为动态绑定,因为JVM在运行时将内存分配给对象'a'而不是编译时。
有关动态绑定的更多详细信息,请检查以下链接:
我还建议您在计算机上安装eclipse并在调试模式下运行代码。 这是学习代码的最佳方式。