今天我们继续来深入的学习一下Java的异常处理机制
异常分类
可检测异常:
可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或 声明规则,不捕捉这个异常,编译器就通不过,不允许编译
非检测异常:
非检测异常不遵循处理或者声明规则。在产生此类异常时,不一定非要采取任何适当 操作,编译器不会检查是否已经解决了这样一个异常
RuntimeException
类属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类 异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译器检查 与处理或声明规则的限制。实际上RuntimeException及其子类型表达的都是因为程序漏洞(BUG), 即:逻辑不严谨等原因导致的。这类异常都是通过修复代码可完全避免的异常,因此不应当由异常处 理机制来处理
IllegalArgumentException:抛出的异常表明向方法传递了一个不合法或不正确的参数 NullPointerException:当应用程序试图在需要对象的地方使用 null 时,抛出该异常 ArrayIndexOutOfBoundsException:当使用的数组下标超出数组允许范围时,抛出该异常 ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常 NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换 为适当格式时,抛出该异常。
throw关键字
throw可以允许我们主动在方法中对外抛出一个异常 通常以下情况我们会这样做:
1:方法中出现了一个异常,但是该异常不应当在当前方法中被处理
2:方法运行过程中出现了一个满足语法但是不满足业务的情况(本案例演示)
public static void main(String[] args) {//不要在main方法中使用throws
Person p = new Person(1000);
try {
p.setAge(10000);//满足语法,但是不满足业务场景
} catch (IllegalAgeException e) {
throw new RuntimeException(e);
}
System.out.println("此人年龄:" + p.getAge());
}
throws关键字
简介
注意,永远不应当在main方法上使用throws!!
注意,永远不应当在main方法上使用throws!!
注意,永远不应当在main方法上使用throws!!
throws用来在声明方法时同时声明该方法可能抛出的异常,用于通知调用方添加处理该异常的手段。 当一个方法中使用throw抛出一个非RuntimeException的异常时,就要在该方法上使用throws声明这个 异常的抛出。此时调用该方法的代码就必须处理这个异常,否则编译不通过。
package exception;
/**
* 测试异常的抛出
*/
public class Person {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) throws Exception {
if(age<0||age>100){
//使用throw对外抛出一个异常
// throw new RuntimeException("年龄不合法!");
//除了RuntimeException之外,抛出什么异常就要在方法上声明throws什么异常
throw new Exception("年龄不合法!");
}
this.age = age;
}
}
当我们调用一个含有throws声明异常抛出的方法时,编译器要求我们必须处理这个异常,否则编译不通 过。 处理手段有两种:
1、使用try-catch捕获并处理这个异常
2、在当前方法(本案例就是main方法)上继续使用throws声明该异常的抛出给调用者解决。 具体选取 那种取决于异常处理的责任问题。
public class ThrowDemo {
public static void main(String[] args){
System.out.println("程序开始了...");
try {
Person p = new Person();
p.setAge(100000);//典型的符合语法,但是不符合业务逻辑要求
System.out.println("此人年龄:"+p.getAge()+"岁");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("程序结束了...");
}
}
重写方法的规则
当一个子类重写超类含有throws声明异常抛出的方法时,针对throws的重写规则 例
1、允许不再抛出任何异常
2、允许仅抛出部分异常
3、允许抛出超类方法声明抛出异常的子类型异常
4、不允许抛出额外异常(超类方法没有声明的且不存在继承关系的)
5、不允许抛出超类方法抛出异常的超类型异常
// public void dosome()throws IOException, AWTException {}
// 子类可以不再抛出任何异常
// public void dosome(){}
// 子类可以仅抛出超类方法声明异常的部分异常
// public void dosome()throws IOException {}
// 子类方法可以抛出超类方法声明抛出异常的子类型异常
// public void dosome()throws FileNotFoundException {}
// 不允许抛出额外异常.超类方法没有声明的,且与声明的异常不存在继承关系的
// public void dosome()throws SQLException {}
// 不允许抛出超类方法声明异常的超类型异常
// public void dosome()throws Exception {}
自定义异常
自定义异常通常用来定义那些业务上的异常问题。
定义自定义异常需要注意以下问题:
1、异常的类名要做到见名知义
2、需要是Exception的子类
3、提供超类异常提供的所有种类构造器
public class IllegalAgeException extends Exception{
public IllegalAgeException() {
}
public IllegalAgeException(String message) {
super(message);
}
public IllegalAgeException(String message, Throwable cause) {
super(message, cause);
}
public IllegalAgeException(Throwable cause) {
super(cause);
}
public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}