在java中使用父引用类型访问变量

在java中使用父引用类型访问变量,java,Java,我创建了两个类——Parent和Child,都是这样的: Parent.java public class Parent { String name = "Parent"; } public class Test { public static void main(String[] args) { Parent p = new Parent(); Child c = new Child(); System.out.printl

我创建了两个类——
Parent
Child
,都是这样的:

Parent.java

public class Parent {
    String name = "Parent";
}
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);
    }

}
Child.java

public class Child extends Parent {
    String name = "Child";
}
子类正在隐藏父类实例变量
name

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

Test.java

public class Parent {
    String name = "Parent";
}
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
。但根据程序,我的理解是不正确的,这个概念只适用于被子类重写的方法


你能解释一下为什么实例变量与方法不同吗?

实例变量没有重写

您的
子类
有两个
名称
实例变量。子类中的一个隐藏父类中的一个(顺便说一句,它们不必都是同一类型)


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

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


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

只需将拇指规则保持为:

  • 在方法重写的情况下,引用变量并不重要,但重要的是该变量所引用的实际对象类型
  • 在变量阴影的情况下,引用变量很重要,而该变量所引用的实际对象类型并不重要
  • 考虑您的以下修改类:

    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");
       }
    }
    
    现在将在测试类中运行此
    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
    

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

    在编译期间,对变量的访问总是以解析静态类型(即:变量的类型)的方式进行解析。但是,这些方法是由实际对象的运行时类型确定的。 在这个程序中,s.name将在编译时解析。 也就是说,s.name将解析为Shape.name
    显然,现在的输出必须是形状。

    顺便说一句,
    子级扩展父级
    毫无意义。@MarounMaroun,我没听明白你的意思,我的意思是
    子级
    不一定是父级,这不是继承的好例子。@MarounMaroun,明白了,我只是想看看在继承中隐藏变量的行为。现在很清楚为什么它调用父实例变量了。谢谢
    顺便说一句,它们不必都是同一类型的
    ,这是一个很好的观点,我不知道。刚刚在我的程序中验证过。谢谢回答和评论中的“他们”是什么意思?你是说名称变量类型,它们可以是String和int吗?@user3320018的“它们”是指两个名称相同的变量,是的,它们可以是String和int。太好了,现在有意义了。