异常作用1就是保证程序出现问题时、且不知道如何处理时,终止程序执行,阻止错误影响范围 扩大,作用2时将错误报告出去。
Java异常分类
Java异常类的继承关系
Error子类错误一般都比较致命,例如内存即将耗尽OutOfMemoryError,程序需要终止执行,不需要捕捉,捕捉也没有什么意义;Exception异常有IndexOutBoundsException,这类异常出现对程序影响不是特别严重,程序依然可以执行,只需捕捉到之后,做出相应处理即可。
受检查异常自己理解是语言本身设计时的一种缺陷,使用这些某些类或者语法,出现的异常位置和异常类型可以被预测,JVM并且无法处理,所以需要抛出。运行时异常,一般由开发人员不合适的逻辑引起,无法预料的错误,捕捉意义不大。
异常捕捉过程
自定义异常和异常方法重写限制
自定义异常
/**
*年龄合法性异常类,继承了受检查异常,在抛出和捕捉该异常的地方都要进行声明
*/
public class InvalidAgeException extends Exception{
public InvalidAgeException(){}
public InvalidAgeException(String msg){
super(msg);
}
}
**
* 手机号合法性异常,继承运行时异常,可以不用捕捉,jVM会自动捕捉
*/
class InvalidPhoneException extends RuntimeException{
public InvalidPhoneException(){}
public InvalidPhoneException(String msg){
super(msg);
}
}
两个测试类
public class User {
private Integer age;
private String phone;
public User(){}
public User(Integer age, String phone) {
this.age = age;
this.phone = phone;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) throws InvalidAgeException {
if(age < 0){
//抛出手机号不合法异常对象InvalidAgeException
throw new InvalidAgeException("年龄填写不合法,age="+age);
}
this.age = age;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
if(phone.trim().length()!=11){
throw new InvalidPhoneException("请检查手机号码合法性,phone="+phone);
}
this.phone = phone;
}
}
public class TestException {
public static void main(String[] args) throws InvalidAgeException {
User user = new User();
try{
user.setAge(-9);
user.setPhone("1233456789");
}catch (Exception e){
e.printStackTrace();
System.out.println(e);
}
System.out.println("hje");
}
}
运行结果:
异常方法重写限制
原因:SocketException不属于FileNotFoundException和其子类。
子类重写父类方法,抛出的异常类在基类范围内,这也是java继承特性决定。
异常使用原则
1、具体明确:抛出的异常越明确越好,捕捉异常时可以针对不同的异常使用多个catch块进行捕捉。
2、try模块应该越小越好,针对具体的异常进行捕捉,和上一条具体明确对应,方便后面新写异常时进行维护。
3、延迟捕获:属于自己处理的异常,自己处理,不能准备识别的异常应该抛给调用者,好处时,异常可以同一处理,不用调用链的每一步都对每种异常进行处理,过多的异常代码影响对正常业务代码的理解。
4、对于不能进一步处理的受检查异常,为了代码的简洁性,应该使用try catch或者使用lombok的@SneakThrows吃掉受检查异常,使用try catch将受检查异常转化为运行时异常。