1700449135
1700449136
Base base=new Base();
1700449137
1700449138
}catch(IOException e){
1700449139
1700449140
//异常处理
1700449141
1700449142
}
1700449143
1700449144
}
1700449145
1700449146
然后,我们期望把new Base()替换成new Sub(),而且代码能够正常编译和运行。非常可惜,编译通不过,原因是Sub的构造函数抛出了Exception异常,它比父类的构造函数抛出的异常范围要宽,必须增加新的catch块才能解决。
1700449147
1700449148
可能有读者要问了,为什么Java的构造函数允许子类的构造函数抛出更广泛的异常类呢?这正好与类方法的异常机制相反,类方法的异常是这样要求的:
1700449149
1700449150
//父类
1700449151
1700449152
class Base{
1700449153
1700449154
//父类方法抛出Exception
1700449155
1700449156
public void method()throws Exception{
1700449157
1700449158
}
1700449159
1700449160
}
1700449161
1700449162
//子类
1700449163
1700449164
class Sub extends Base{
1700449165
1700449166
//子类方法的异常类型必须是父类方法的子类型
1700449167
1700449168
@Override
1700449169
1700449170
public void method()throws IOException{
1700449171
1700449172
}
1700449173
1700449174
}
1700449175
1700449176
子类的方法可以抛出多个异常,但都必须是被覆写方法的子类型,对我们的例子来说,Sub类的method方法抛出的异常必须是Exception的子类或Exception类,这是Java覆写的要求。构造函数之所以与此相反,是因为构造函数没有覆写的概念,只是构造函数间的引用调用而已,所以在构造函数中抛出受检异常会违背里氏替换原则,使我们的程序缺乏灵活性。
1700449177
1700449178
子类构造函数扩展受限
1700449179
1700449180
子类存在的原因就是期望实现并扩展父类的逻辑,但是父类构造函数抛出异常却会让子类构造函数的灵活性大大降低,例如我们期望这样的构造函数。
1700449181
1700449182
class Sub extends Base{
1700449183
1700449184
public Sub()throws Exception{
[
上一页 ]
[ :1.700449135e+09 ]
[
下一页 ]