Java继承字段

时间:2017-04-24 03:59:24

标签: java inheritance

我无法理解以下输出。

我不知道为什么输出为10,我认为行A a = new B()创建了一个B类的新实例,我认为结果应该是20

class A {
    int i = 10;
}

class B extends A {
    int i = 20;
}

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

        System.out.println(a.i);
    }
}

为什么会这样......请解释一下。

5 个答案:

答案 0 :(得分:33)

首先,请参阅Hiding Fields(强调添加)

  

在一个类中,与超类中的字段同名的字段会隐藏超类的字段,即使它们的类型不同

换句话说,这不是" t"继承"因为您实际隐藏A i B i后面的A,并且您正在使用{{B b = new B()的引用对象1}},所以你得到它的领域。如果您执行了20,则会按预期看到class A { public int get() { return 10; } } class B extends A { @Override public int get() { return 20; } }

如果您希望使用真正的覆盖,请尝试使用方法。

A a = new B();
System.out.print(a.get()); // 20

class A {
    int i = 10;
}

class B extends A {
    int i = 20;

    @Override 
    public String toString() { 
        return String.format("super: %d; this: %d", super.i, this.i);
    }
}

如果您真的想同时查看两者,请参阅此示例。

A a = new B();
System.out.print(a); // super: 10; this: 20

并且

User.unscoped.all

答案 1 :(得分:19)

在java中,您无法覆盖实例变量。您获得的输出是预期的。在Java中,您只能覆盖实例方法而不是实例变量。

如果你想要20作为输出,你可以在这些实例变量上使用getter方法。

 class A {
    int i = 10;

    int getI() {
        return i;
    }
}

class B extends A {
    int i = 20;

    int getI() {
        return i;
    }
}

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

        System.out.println(a.getI());
    }
}

答案 2 :(得分:12)

多态性不适用于Java中的字段。评估变量决策是在编译时进行的,因此始终会访问基类变量。

答案 3 :(得分:4)

因为你定义了两个变量:一个在子类B中,一个在超类A中具有相同的名称。

A a = new B();
a.i; // refers to A.i

如果您将A投射到B,则会访问B.i

System.out.println(((B)a).i);

我认为您需要使用1个变量:

class A {
    int i;

    public A() {
        i = 10;
    }
}

class B extends A {
    public B() {
        i = 20;
    }
}

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

        System.out.println(a.i); // will print 20
}

答案 4 :(得分:1)

成员变量i已在class A中定义。

为了达到您的目的,请更改class B,如下所示:

class B extends A {
    public B() {
      i = 20;
    }
}