【问题标题】:Access a variable using parent reference type in java在java中使用父引用类型访问变量
【发布时间】:2015-06-30 08:24:54
【问题描述】:

我创建了 2 个类 - ParentChild,都像这样:

Parent.java

public class Parent {
    String name = "Parent";
}

Child.java

public class Child extends Parent {
    String name = "Child";
}

子类正在遮蔽父类实例变量name

我已经创建了一个这样的主程序:

Test.java

public class Test {

    public static void main(String[] args) {
        Parent p = new Parent();
        Child c = new Child();

        System.out.println(p.name);
        System.out.println(c.name);

        Parent pc = new Child();
        System.out.println(pc.name);
    }

}

程序的输出是这样的:

Parent
Child
Parent

现在我不清楚何时尝试访问pc.name,然后根据上述输出得到Parent 的输出,而不是Child

我的理解是这样的,我创建了一个Parent 类型的引用变量pc,但它指向Child 对象作为我的程序。因此,在程序运行时,java 在堆内存中为子类创建一个对象,由于子类隐藏了name 变量,pc.name 的输出将是Child。但是根据程序,我的理解是不正确的,这个概念只适用于被子类覆盖的方法。

您能否解释一下为什么实例变量与方法的情况不同?

【问题讨论】:

  • 顺便说一句,Child extends Parent 没有意义..
  • @MarounMaroun,我没找到你
  • 我的意思是Child不一定是Parent,这不是继承的好例子。
  • @MarounMaroun,好的,我只是想看看在继承中隐藏变量的行为。

标签: java


【解决方案1】:

实例变量没有覆盖。

您的Child 类有两个name 实例变量。 Child 类中的一个隐藏了 Parent 类中的一个(顺便说一句,它们不必都是同一类型)。

当您通过Parent 引用访问name 时,您将获得Parent 类的name 变量。当您通过 Child 引用访问 name 时,您将获得 Child 类的 name 变量。

【讨论】:

  • BTW, they don't have to both be of the same type,这是一个好点,我不知道。刚刚在我的程序中验证。谢谢
  • 答案和评论中的“他们”是什么意思?你的意思是名称变量类型,可以是String和int吗?
  • @user3320018 “他们”是指具有相同名称的两个变量,是的,它们可以是 String 和 int。
  • 太好了,现在说得通了。
【解决方案2】:

对字段的访问总是由静态类型(即:变量的类型)决定的。这与由实际对象的运行时类型确定(也称为“已解决”、“绑定”)的方法形成对比。

换句话说:对于字段访问,编译器在编译时确定将要被访问。在您的示例中,您访问pc.name。编译器检查pc 变量的类型,发现它是Parent 类型,因此生成访问Parent 类的.name 字段的代码。

【讨论】:

  • 现在很清楚为什么它调用父实例变量了。谢谢
【解决方案3】:

保持拇指规则为:

  1. 在覆盖方法的情况下,引用变量无关紧要,重要的是该变量所引用的实际对象类型。
  2. 在变量阴影的情况下,引用变量很重要,而该变量所引用的实际对象类型无关紧要。

考虑以下修改过的类:

public class Parent {
    String name = "Parent";
    public void printName(){
    System.out.println("Parent Method");
  }
}

public class Child extends Parent {
  String name = "Child";
  public void printName(){
    System.out.println("Child Method");
   }
}

现在将在 Test Class 中运行这个 main() 方法:-

public class Test {

public static void main(String[] args) {
    Parent p = new Parent();
    Child c = new Child();

    System.out.println(p.name); // will print Parent's name
    System.out.println(p.printName());// will call Parent
    System.out.println(c.name); // will print Child's name
    System.out.println(c.printName());// will call Child

    Parent pc = new Child();
    System.out.println(pc.name);// will print Parent's name
    System.out.println(pc.printName());// will call Child
   }
}

这将按照我上面所说的规则打印以下内容:-

Parent 
Parent Method
Child
Child Method
Parent
Child Method

【讨论】:

    【解决方案4】:

    当你在java中创建一个子类对象时,在内部也会创建父类对象,父类对象将被super关键字引用。 现在,使用 Parent 引用,您可以从 Child 类中访问什么? 答。使用父引用,您只能访问 Child 类的继承和重写方法。 换句话说,只能使用 Parent 引用调用方法。 现在的问题是当您将它与变量/字段一起使用时会发生什么 - 首先,了解如何解决对变量的访问?

    在编译时始终以解析静态类型(即:变量的类型)的方式解析对变量的访问。但是,由实际对象的运行时类型确定的方法。 在这个程序中,s.name 将在 COMPILE-TIME 本身被解析。 也就是说,s.name 将被解析为 Shape.name 显然现在的输出必须是 Shape。

    【讨论】:

      猜你喜欢
      • 2012-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 2013-03-01
      • 2013-11-30
      相关资源
      最近更新 更多