11

我正在学习java。我对继承有疑问。当子类扩展父类并且父类具有引用父类中声明的实例变量的方法时。但是子类 dint 覆盖了这个方法,并声明了与父类同名的实例变量。在这种情况下,将引用来自子级的实例变量或将引用父级。下面是代码片段

class Parent {
    int a;
    Parent() {
        System.out.println("in Parent");
        a = 10;
    }
    void method() {
        System.out.println(a);
    }
}
class Child extends Parent {
    int a;
    Child() {
        System.out.println("in Child");
        a = 11;
    }
}

public class Test {
    public static void main(String args[]) throws IOException {
        Parent p1 = new Child();
        p1.method();
    }
}

我得到的输出是

10
岁的父母

有人可以让我理解为什么它引用父类的实例变量a而不是子类的a.

另一个疑问是,我理解隐藏方法,当父类和子类中有静态方法时也声明了具有相同签名的静态方法。这里隐藏意味着什么?什么方法被隐藏了?如果它是父方法,你能解释一下吗?
提前致谢。

4

6 回答 6

20
  1. Java 实例变量不能在子类中被覆盖。Java 继承不是那样工作的。

  2. 在您的示例中,没有方法隐藏(或覆盖或重载)正在进行。

  3. 虽然隐藏了实例变量。在类child中, 的声明a隐藏了ain的声明parent,并且类中所有的引用都指向a了not 。childchild.aparent.a

为了更清楚地说明这一点,请尝试运行:

public static void main(String args[]) throws IOException {
    child c1 = new child();
    parent p1 = c1;

    System.out.println("p1.a is " + p1.a);
    System.out.println("c1.a is " + c1.a);
    System.out.println("p1 == c1 is " + (p1 == c1));
}

它应该输出:

    p1.a is 10
    c1.a is 11
    p1 == c1 is true

这表明有一个对象具有两个名为a... 的不同字段,如果访问权限允许,您可以获取它们的两个值。


最后,您应该学会遵循标准的 Java 标识符约定。类名应始终以大写字母开头。

于 2013-02-18T10:05:29.353 回答
2

Instance variables are not overriden in sub-class. 如果你在你的类中定义了一个与你的超类同名的变量,它被称为变量的阴影 inheritance and polymorphism不适用于实例变量。如果您在父类中定义 method() 并在子类中覆盖它。由于运行时多态性打印11 ,下面将调用 Child 的方法()

 parent p1 = new child();
  1. 调用子构造函数
  2. 使用 super() 调用调用父级的构造函数
  3. 打印“在父级中”并将父级的 a 初始化为 10
  4. print's in child 并将 Childs a 初始化为 11

        p1.method();// this invokes Child's method() during run-time
    
于 2013-02-18T10:04:52.117 回答
1

当你这样做时

父 P1=new Child();

JVM 所做的是

               first  Initialize Parent()

                         ||

               second Initialize Child()

因此,首先调用 Parent 构造函数,然后调用 child's ,但输出值将是 11 ,因为 p1 指的是 child 的对象。

于 2013-02-18T10:11:17.310 回答
1

由于您没有在子类中覆盖 method() ,因此当声明时,

parent p1 = new child();

执行时,method() 的父版本将被执行,并且父类唯一知道的值是它自己的 a。因此它将打印 a=10 (因为它当时在堆栈上)。

最后,您只是将变量 a 从父类隐藏到子类。

于 2013-02-18T10:16:38.397 回答
0

问题是您创建了一个子实例并将其存储在父实例的引用中。因此,当您访问对象的属性时,JVM 会引用父级的变量值。

如果它是子类的引用变量,您将收到子类的变量值。

以上是Java的一个特性。

于 2013-02-18T10:05:54.380 回答
0

在创建父实例时。所以在运行时编译器调用父对象,试试下面的代码。

public static void main(String args[]) throws IOException {
    child c1 = new child();
    c1.method();
}
于 2013-02-18T10:08:01.600 回答