我创建了两个类 - Parent
和Child
,两者都是这样的:
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} }。但是根据程序,我的理解是不正确的,这个概念仅适用于被子类重写的方法。
请问您能解释为什么实例变量与方法相比有所不同吗?
答案 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)
将拇指规则保持为:
考虑以下修改过的你的类:
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。