继承的细节--构造方法

继承和多态概念还有一些相关的细节,具体包括:

  • 构造方法 now!

  • 重名与静态绑定

  • 重载和重写

  • 父子类型转换

  • 继承访问权限(protected)

  • 可见性重写

  • 防止继承(final)

cop.kujiale|owt.khrd|pdl.i18n|service.message-service

构造方法

构造方法与类同名且没有返回值。

构造方法的语句格式:

1
2
3
public 构造方法名() {
//初始化代码
}

只能在对象实例化(new 对象)的时候被调用。

子类可以通过super(…)调用父类的构造方法。如果子类没有通过super(…)调用,则会自动调用父类的默认构造方法。

如果父类没有默认构造方法,如下所示:

1
2
3
4
5
6
7
//父类
public class Base {
private String member;
public Base(String member) {
this.member = member;
}
}

上方代码中的类只有一个带参数的构造函数,没有默认构造方法。

这个时候,它的任何子类都必须在构造方法中通过super(…)调用Base的带参数的构造方法。

如下所示,否则Java会提示编译错误。

1
2
3
4
5
6
//子类
public class Child extends Base{
public Child(String member) {
super(member); //调用Base的带参构造方法
}
}

避免父类的构造方法调用可重写的方法

如果在父类构造方法中调用了可被重写的方法,则可能会出现意想不到的结果。

父类代码如下:

1
2
3
4
5
6
7
8
9
//父类
public class Base {
public Base() {
test(); //构造函数中调用test方法
}

public void test() {
}
}

子类代码如下:

1
2
3
4
5
6
7
8
9
10
11
//子类
public class Child extends Base{
private int a = 123;

public Child() {
}

public void test() {
System.out.println(a);
}
}

子类有一个实例变量a,a初始赋值为123。子类重写了test方法,要输出a的值。

使用代码如下:

1
2
3
4
public static void main(String[] args) {
Child c = new Child();
c.test();
}

输出结果:

1
2
0
123

第一次输出0,是在new过程中输出的。

new过程中,首先初始化父类Base,父类构造方法调用test(),test被子类重写了,就会调用子类的test方法。

子类方法访问子类实例变量a,这个时候子类的实例变量的赋值语句和构造方法还没有执行,所以输出的默认值是0。

通过上面的例子,可以得出结论——在父类构造方法中调用可被子类重写的方法,是一种不好的实践,容易引起混淆,应该只调用private的方法

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2021 Silver Shaded
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信