将继承类的对象分配给超类的引用

时间:2014-06-01 15:46:09

标签: java

鉴于以下代码:

public class A {
     int at=2;

    public int m(int i){return at+i;}
}

class B extends A {
     int at=3;

        public int m(int i){return at+5*i;}
}

public class Main {

    public static void main(String args[]){
        A x = new B();

        System.out.println("Output "+x.m(x.at));
    }
}

输出为13。

它是如何工作的? 我知道它需要来自B的方法,但是参数呢?

3 个答案:

答案 0 :(得分:6)

看表达式:x.m(x.at)。由于x被归档为Ax.at将引用at中的A字段。

然而,在方法方面,它变得更加复杂。虽然x被声明为A,但x实际上属于B类型,因此方法m将从x的实践中调用class,B

也许this可以提供帮助。

答案 1 :(得分:3)

实际上,您有两个at字段,其中一个在A中声明,另一个在B中声明。 m中的方法A引用at中的字段A; m中的方法B是指at中提交的B。方法被覆盖,字段不被覆盖。 x被声明为A的实例,因此x.at为2.当您调用方法m时,将调用重写的方法(B.m(2)),以便获得3+ 5 * 2 = 13。

在这种情况下,Java Language specification应该告诉你什么是对的,为什么。可以在8.3. Field Declarations

中找到对此问题的回答
  

如果类声明了具有特定名称的字段,那么   据说该领域的声明隐藏任何和所有可访问的   超类中具有相同名称的字段的声明,和   班级的超级接口。

     

如果使用限定名称(第6.5.6.2节),则可以访问隐藏字段   它是静态的,或者使用包含的字段访问表达式   关键字super(§15.11.2)或强制转换为超类类型。

强制转换为超类类型。

答案 2 :(得分:1)

变量不会覆盖类似方法。因此,变量值取决于引用变量,而不取决于此引用变量引用的实例。

示例:在您的情况下。在main()方法

A x = new B();

引用变量x的类型为A,它包含类型B实例的引用。

因为X是A类型。当你写x.at时,它引用的是A类变量。