使用java

时间:2015-06-30 08:24:54

标签: java

我创建了两个类 - ParentChild,两者都是这样的:

Parent.java

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

Child.java

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

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输出。

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

请问您能解释为什么实例变量与方法相比有所不同吗?

4 个答案:

答案 0 :(得分:7)

实例变量没有重写。

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

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

答案 1 :(得分:5)

对字段的访问始终由静态类型(即:变量的类型)决定。这与通过实际对象的运行时类型确定的方法(a.k.a"已解决","绑定")形成对比。

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

答案 2 :(得分:1)

将拇指规则保持为:

  1. 如果方法覆盖,引用变量无关紧要,但重要的是此变量所指的实际对象类型。
  2. 如果是变量阴影,则引用变量很重要,而此变量所指的实际对象类型无关紧要。
  3. 考虑以下修改过的你的类:

    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
    

答案 3 :(得分:0)

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

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