当有继承发生时,会伴随着重载、覆写(包括接口方法的实现)、构造器的重写等行为。此时,如果基类或是接口的方法存在异常声明,那么导出类或是接口的实现类的对应方法该如何声明异常?同时对这些方法的调用该如何捕捉异常?下面就这2个问题进行探讨,你会看到,针对覆写和构造器的重写是2种完全不同的处理方式(针对重载则没有任何限制)。代码如下:
//@file Example1.java
class ExtException extends Exception {}
class AnotherException extends Exception {}
class Base
{
public void func() {}
public void func2() throws Exception {}
public void func3() throws ExtException {}
public Base() throws Exception {}
public Base(int i) throws Exception {}
//public Base(float f) throws ExtException{} //Error No.5: every other constructor will call the default constructor; same as Error No.4
}
interface Inf
{
public void func2() throws ExtException;
//public void func3() throws AnotherException; //Error No.3: base and interface conflicts
public void func4() throws Exception;
public void func5() throws Exception;
}
class ExtImp extends Base implements Inf
{
//public void func() throws ExtException{} //Error No.1: if base function has no exception declaration, overriding CANNOT add one
//public void func2() throws Exception {} //Error No.2: cannot implement interface; base and interface conflicts
public void func2() throws ExtException {} //implement interface and use Hint No.2
//public void func3() throws ExtException {} //Error No.3
//public void func3() throws AnotherException {} //Error No.3
public void func4() {} //Hint No.1: if base function has exception declaration, overriding CAN ommit
public void func5() throws ExtException {} //Hint No.2: if base function has exception declaration, overriding CAN declare ext exception
//public ExtImp() {} //Error No.4: ext's construcor must declare the exception the base constructor declare
public ExtImp() throws Exception {}
//public ExtImp() throws ExtException {} //Error No.4
public ExtImp(int i) throws Exception, ExtException {} //Hint No.3: once ext decalres throwing the base's exception, it CAN declare other exception (不一定非要是父类声明异常的子类), see Example2.java
//public ExtImp(float f) throws ExtException{} //Error No.5
}
//@file Example2.java
class ExtException extends Exception {}
class AnotherException extends Exception {}
class ThirdException extends Exception {}
class FourthException extends ThirdException {}
class Base
{
public Base() {}
public Base(int i) throws ExtException {}
public Base(float f) throws ExtException {}
public void func() throws ThirdException { System.out.println("Base.func()");}
}
class Ext extends Base
{
public Ext() throws Exception {} //Hint No.4: ext's constructor CAN add exception declaration
public Ext(int i) throws ExtException, AnotherException {} //Hint No.4
public Ext(float f) throws Exception {} //Hint No.5: ext's constructor can declare base exception
public void func() throws FourthException { System.out.println("Ext.func()");}
}
public class Example2
{
public static void main(String[] args)
{
try
{
Ext e = new Ext(5);
e.func();
}
catch (ExtException ee) {}
catch (AnotherException ae) {}
catch (FourthException fe) {} // ***DIFFERENCE***
try
{
Base b = new Ext(5);
b.func();
}
catch (ExtException ee) {}
catch (AnotherException ae) {}
catch (ThirdException te) {} // ***DIFFERENCE***
}
}
//output:
/*
Ext.func()
Ext.func()
*/
针对覆写方法,有以下几点原则:
1. 如果基类方法没有声明异常,那么导出类的覆写方法也不能声明异常(Error No.1)。
2. 如果基类方法有声明异常,那么导出类的覆写方法可以:(1)不声明异常;(2)声明抛出基类方法的异常;(3)声明抛出基类方法异常的导出类。(Hint No.1 & Hint No.2)
3. 如果基类和接口有同签名方法,且导出类实现了接口,如果基类方法和接口方法声明的异常不同,则称基类与接口冲突。如果基类方法抛出的异常和接口方法声明的异常存在继承关系,则实现接口的导出类必须声明抛出导出异常(子异常)(Error No.2);如果如果基类方法声明的异常和接口方法声明的异常不存在继承关系,则冲突不可调和,需要修改基类或是接口(Error No.3)。
4. 由Example2.java可见,对于向上转型
Base b = new Ext(5),调用b.func()虽然会动态绑定调用Ext的func()方法,可是异常捕捉必须按照Base的func()方法的异常声明来捕捉(见DIFFERENCE处)
。
针对构造器的重写,有以下几点原则:
1. 这里应该持这么一种观点,基类的带参构造器和导出类的所有构造器都默认调用了基类的默认构造器,Base(int i)调用了Base(),Ext()调用了super(),Ext(int i)调用了super(i),依次类推。所以一旦基类的默认构造器声明了异常,那么基类的带参构造器和导出类的所有构造器都必须声明异常,异常类型可以是基类默认构造器的异常或是其基类,而决不能是其导出类(Error No.4, Error No.5 & Hint No.5) (与覆写方法抛异常的情况刚好相反)
。
p.s.
导出类构造器虽然不能声明导出异常,不过可以抛出导出异常,如:
class Base
{
public Base() throws NullPointerException {}
}
class Ext extends Base
{
public Ext() throws Exception
{
throw new NullPointerException();
}
}
所以牢记:声明异常和实际抛出异常完全是两码事
。
2. 如1.所说,构造器的重写实际是调用关系,所以一旦默认构造器没有声明异常,那么其他构造器就可以随便添加异常声明(Hint No.3 & Hint No.4)。
分享到:
相关推荐
0X0E中学算术前置知识0X0D数学库函数正文有了三角函数、反三角函数、对数函数、求幂运算,中学阶段涉及的所有具体的数值计算基本就都可以求解。求此表达式的值:第
0X2B循环for前置知识0X29再谈循环正文Lua除了while和repeat语句还提供了一种for循环语句.while和repeat语句循环终止条件可以是任
目录图例Stage1 入门Stage2 基础Stage3 字符串处理Stage4 理解函数Stage5 表结构Stage6 流程控制Stage7 模块Stage
1. 度量脚本执行时间 2. 记录时间 3. 计算时间间隔
域的定义如果交换环还额外满足以下条件,则称为域:乘法单位元和加法单位元不相等(1不等于0)。由于存在乘法逆元,就意味着可以进行“除法”,所以有的书上也把域称作
安全运营相关文章本篇整理一些安全运营相关的高质量文章[2] 体系化的WAF安全运营实践, 安全研究与实践,
NULL 博文链接:https://aoyi.iteye.com/blog/659179
NULL 博文链接:https://aoyi.iteye.com/blog/631929
NULL 博文链接:https://aoyi.iteye.com/blog/723571
STM8S207中断系统##pragma 0x原因.pdf,介绍中断的
#0 0x00002b9405ea1c38 in __lll_mutex_lock_wait () from /lib64/libc.so.6 #1 0x00002b9405e45e5f in _L_lock_4026 () from /lib64/libc.so.6 #2 0x00002b9405e42df1 in free () from /lib64/libc.so.6 #3 0x00002...
#define up 0x4800 #define down 0x5000 #define left 0x4b00 #define right 0x4d00 #define esc 0x011b #define enter 0x1c0d #define A 0x1e61 #define S 0x1f73 #define D 0x2064 #define W 0x1177 #define space...
Struts的java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource异常的解决方法
试图加载格式不正确的程序。 (异常来自 HRESULT0x8007000B)
部分指令下载后有全部:#define PU 0x01 #define STOP 0x02 #define RESET 0x03 #define CLI_INT 0x04 #define RD_STATUS 0x05 #define RD_PLAY_PTR 0x06 #define PD 0x07 #define RD_REC_PTR 0x08 #define RD_DEVID...
从0x0020到0xffef的完整码表。GBK没有的用0x0000代替。 用户可以自行替换成想要显示的字符,或者自行截取所需要的范围 本码表由http://cs.nyu.edu/~yusuke/tools/unicode_to_gb2312_or_gbk_table.html 转换而成,...
#define PCD_IDLE 0x00 //取消当前命令 #define PCD_AUTHENT 0x0E //验证密钥 #define PCD_RECEIVE 0x08 //接收数据 #define PCD_TRANSMIT 0x04 //发送数据 #define PCD_TRANSCEIVE 0x0C //发送并接收数据 #define ...
1 具有菜单项 2 具有保存文件功能 3 具有帮助系统 ***********************************************/ #include ...#define ESC 0x011b ...#define ENTER 0x1c0d ...#define SCROL_LOCK 0x10
VL53L0X 开发参考使用手册,初学者必备
MRS R1,CPSR BIC R1,R1,#0x1F ORR R1,R1,#0x1B MSR CPSR_cxsf,R1