class Person{
String name = "person";
}
class Son extends Person {
String name = "son";
}
public class Test {
public static void main(String[] args){
Person p = new Son();
System.out.println(p.name);
}
}
结果为person。
为什么不是son?
因为Person p = new Son();
就是把子类转型为父类
子类转型为父类的规则:
只能调用父类的属性
只能调用父类未被复写的方法
只能调用被子类复写的方法
----------------------------------------------------------------------------------------------------------------
而属性并不能被复写,只是重名了。对此我们可以验证一下:
在父类添加一个fun(){System.out.println("父类方法");}
在子类复写方法fun(){System.out.println("子类方法");}
然后在主方法中:
Son p2 = new Son();
p2.run(); //子类直接调用fun方法
((Person )p2).run(); //转成父类后调用fun方法
System.out.println(p2.name); //子类直接调用name属性
System.out.println(((Person )p2).name); //转成父类后调用name属性
结果输出是:
子类方法
子类方法 <-------由于方法被子类覆盖了所以即使转型成父类也同样是调用被复写的方法
son
person <-------虽然属性被重名了,但并不能覆盖掉父类的属性!!
通俗的说就是:父类中的name属性属于父类的,子类的name属性属于子类的。
所以子类转型为父类后调用的name是父类中name属性,且也只能调用父类的属性。
javac命令 生成.class文件这个过程是不是可以理解成编译,static变量,static块等在这个过程中被初始化,前期绑定发生在这个阶段;java命令这个过程是不是理解成执行,后期绑定发生在这过程?
追答可以这么理解!
追问p.name-静态绑定,p的地址来自于哪里?是来自于son构造器对person构造器的调用吗?p的地址跟p是怎么弄建立映射的?
追答p指向的是Son对象,因为你创建的是Son。但是,引用是用类型的,你的p被定义为了Person,那么p.name访问的就是Person里的变量,如果你Son p = new Son();那么p.name就是Son里的变量。
本回答被提问者采纳