- 以下讨论都是基于从子类实例进行属性/方法访问出现的情况.建议先看文章-jvm解析与分派
1.从父类方法(未重写)访问属性时,永远都只使用父类属性.
public class Test {
public static void main(String[] args) throws Exception{
F f = new S();
f.prt();// --> 返回f.
}
}
class F{
public String share = "f";
public void prt(){
System.out.println(share);
}
}
class S extends F{
public String share = "s";
}
2.从父类方法(未重写)访问方法f时,若f在子类中重写,则使用子类的重写方法.
//这也是为什么在父类构造器中,不提倡调用可重写方法的原因,因为创建一个子对象时,需要先实例化一个父对象,此时若是调用了子类中的重写方法,则很有可能因为子对象未初始化而造成一些错误(如NullpointException).
public class Test {
public static void main(String[] args) throws Exception{
F f = new S();
f.prt();// --> 返回son.
}
}
class F{
public String share = "f";
public void prt(){
//实际调用了子类的重载方法
f();
}
public void f(){
System.out.println("father");
}
}
class S extends F{
public String share = "s";
@Override
public void f(){
System.out.println("son");
}
}
- 从子类访问父类属性x(可继承)时,若该属性的同名属性在子类中有定义,则直接修改的是子类中的属性,不影响父类属性.如果子类中没有同名属性,则使用父类属性进行操作.
(1) 子重定义父类同名属性,则不影响父类属性
public class Test {
public static void main(String[] args) throws Exception{
F f = new S();
f.prt();// --> 返回son.
}
}
class F{
public String share = "f";
public void prt(){
//实际调用了子类的重载方法
showData();//打印 sss|f
}
void showData(){}
}
class S extends F{
public String share = "s";
@Override
public void showData(){
//修改子类重复定义的属性无影响
share = "sss";
System.out.println(this.share+"|"+super.share);
}
}
(2) 子类直接使用父类的继承属性
public class Test {
public static void main(String[] args) throws Exception{
F f = new S();
f.prt();// --> 返回son.
}
}
class F{
public String share = "f";
public void prt(){
//实际调用了子类的重载方法
showData();
}
void showData(){}
}
class S extends F{
@Override
public void showData(){
//修改子类重复定义的属性无影响
share = "sss";
System.out.println(share == super.share);//打印true
System.out.println(this.share+"|"+super.share);//打印 sss|sss
}
}
- 在父类的可访问方法中调用一个可重写方法,要谨慎,很容易使子类实现者出现错误.
错误示例,以下代码会引发一个StackOverFlow
public class Test {
public static void main(String[] args) throws Exception{
F fout = new S();
fout.invoke();
}
}
class F{
public void invoke(){
fx();
}
public void fx(){}
}
//在不知道父类的方法调用的情况下容易写出以下代码.
//陷入无限递归中
class S extends F{
public void fx(){
this.invoke();
}
}