java犯的小错误_java继承会犯的小错误

注意事项:阅读本文前应该先了解java的继承。本文定位为已经继承基础知识。

一:试图覆盖私有方法

先上代码

1 public classFather {2

3 private voidprint() {4 System.out.println("private print");5 }6

7 public static voidmain(String[] args) {8 Father father = newSon();9 father.print();10 }11

12 }

1 public class Son extendsFather {2

3 public voidprint() {4 System.out.println("public print");5 }6 }

运行father的main方法,我们所期望的输出是public print,但是由于private方法默认为final方法,而且对导出子类是屏蔽的,在这种情况下,子类中的print就是子类中的一个新方法,并非是覆盖了父类的print方法,而且在子类的print方法上是无法加入@override注解的

结论:private方法无法被覆盖重写。

二:在一个构造器内部调用正在构造的对象的某个动态绑定方法

我们都知道,构造器的调用会从最高级的父类开始调用,然后不断反复递归下去。如果在父类的构造器中调用子类的构造方法输出变量,会发生什么?

1 public classFather {2

3 public voiddraw() {4 System.out.println("father draw");5 }6

7 publicFather() {8 System.out.println("father:before draw");9 draw();10 System.out.println("father:after draw");11 }12

13 }

1 public class Son extendsFather {2

3 private int number = 1;4

5 public Son(intnumber) {6 this.number =number;7 System.out.println("init number:" + this.number);8 }9

10 @Override11 public voiddraw() {12 System.out.println("son draw number:" + this.number);13 }14 }

public class MainTest extendsObject{public static voidmain(String[] args) {new Son(5);

}

}

控制台打印:

father:before draw

son draw number:0

father:after draw

init number:5

在测试中,我们new一个son同时传一个5进去,根据构造器的调用,我们知道在构造son的时候要先调用father的构造方法,而在father的构造器中,有调用draw方法。而在子类中,draw方法是将son中的number打印出来,number有一个默认的值为1,那在draw调用过程中,我们期望的输出应该是1,但实际输出的是0.

解决这一问题的关键所在是初始化的过程。在其他任何事物发生之前,分配给对象的储存空间初始化为二进制的零(你可以这样认为,number有一个默认值为1,但是在有这个默认值之前还有一个默认值为0),然后父类的构造器开始调用,再递归调用子类的构造方法,然后按照声明的顺序初始化成员变量。而在这个初始化步骤之前,一切变量都是0,或者null。

三:调用子类覆盖的父类静态方法。

1 public classFather {2

3 public staticString staticGet() {4 return "father static get";5 }6

7 publicString dynaminGet() {8 return "father dynamin get";9 }10 }

1 public class Son extendsFather {2

3 public staticString staticGet() {4 return "son static get";5 }6

7 publicString dynaminGet() {8 return "son dynamin get";9 }10 }

public class MainTest extendsObject{public static voidmain(String[] args) {

Father f= newSon();

System.out.println(f.staticGet());

System.out.println(f.dynaminGet());

}

}

控制台输出:

father static get

son dynamin get

我们期望的输出应该都是son的方法而不是father的方法,但是调用静态方法的时候是father而不是son。这是因为如果某个方法是静态的,那么它的行为就不具有多态性,静态方法是与类绑定的,而不是与单个对象相关联的。子类并不能覆盖父类的静态方法,事实上,在son中的staticGet方法上无法添加@override注解。

四:子类的域可以覆盖父类的域

1 public classFather {2

3 public int number = 3;4

5 public intgetNumber() {6 returnnumber;7 }8 }

1 public class Son extendsFather {2

3 public int number = 2;4

5 public intgetNumber() {6 returnnumber;7 }8

9 public intgetSuperNumber() {10 return super.number;11 }12 }

public class MainTest extendsObject{public static voidmain(String[] args) {

Son s= newSon();

System.out.println(s.getNumber());

System.out.println(s.getSuperNumber());

}

}

控制台输出:

2

3

如果son中的number覆盖掉father的number,那么输出的两个number都应该是2,事实上从son中得到father的number为3,这说明son中的number并没有覆盖掉father中的number。在本例中,son.number和father.number分配到了不同的储存空间。换句话来说,在son中其实包含了两个名为number的变量:它自己的和从father中继承得到的。然而在son中的number所产生的默认域并非father中的number域。因此,为了得到father中的number,必须显式地指明super.field。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值