一、异常的捕获和处理
Java异常结构中定义有Throwable类,Exception和Error是其派生的两个子类。其中Exception表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常;而Error表示Java运行时环境出现的错误,例如:JVM内存资源耗尽等。
1.1 try-catch
package day08;
/**
* java异常捕获机制中的try-catch
* try块是用来括上可能出错的代码片段
* catch块是用来捕获try块中代码抛出的错误并解决。
* @author xxx
*
*/
public class ExceptionDemo1 {
public static void main(String[] args) {
System.out.println("程序开始了");
try {
//String str = null;
//String str ="";
String str = "a";
/*
* JVM在执行代码的过程中若发现了一个异常,则会实例化这种情况的异常实例,
* 并将代码整个执行过程完整设置到异常中来表示该错误报告,设置完毕后将该
* 异常抛出。若抛出异常的这句代码有被try包围,则JVM会检查catch中
* 是否有关注该异常,关注则交给catch解决,否则会将异常抛出到当前方法外。
* 由调用当前方法的代码解决该异常。
*/
System.out.println(str.length());
System.out.println(str.charAt(0));
System.out.println(Integer.parseInt(str));
}catch(NullPointerException e){
System.out.println("出现了空指针");
}catch(StringIndexOutOfBoundsException e){
System.out.println("字符串下标越界了");
/*
* 应在最后一个catch中捕获Exception,避免因未捕获异常导致程序中断。
* 当多个catch捕获不同异常时,这些异常间存在继承关系,那么子类异常要在上
* 先行捕获。父类异常在下。
*/
}catch(Exception e) {
System.out.println("出现未知错误");
}
System.out.println("程序结束了");
}
}
1.2 finally
package day08;
/**
* finally块
* finally块定义在异常捕获机制的最后
* 可以直接跟在try块之后或者最后一个catch块之后。
* finally块中的代码一定执行,无论try块中的代码是否抛出异常,所以通常会
* 把释放资源等操作放在finally中,例如关闭流。
* @author xxx
*
*/
public class ExceptionDemo2 {
public static void main(String[] args) {
System.out.println("程序开始了");
try {
//String str = null;
String str = "";
System.out.println(str.length());
}catch(Exception e) {
System.out.println("出错了");
}finally {
System.out.println("finally中的代码执行了");
}
System.out.println("程序结束了");
}
}
package day08;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
/**
* finally对于流的处理
* @author xxx
*
*/
public class ExceptionDemo3 {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(
new FileInputStream("src/day08/ExceptionDemo3.java")));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}catch(Exception e) {
System.out.println("出错了");
}finally {
if (br != null) {
try {
br.close();
}catch(Exception e) {
System.out.println("关闭流时出错");
}
}
}
}
}
1.3 throw与throws
package day08;
/**
* 用来测试throw与throws
* @author xxx
*
*/
public class Person {
private int age;
public int getAge() {
return age;
}
/*
* 当一个方法中使用throw抛出一个异常时,就要在方法上使用throws声明该类
* 异常的抛出以通知调用者解决。
* 只有RuntimeException及其子类异常使用throw抛出时不强制要求必须使用
* throws声明,其他异常都是强制要求的,否则编译不通过。
*/
public void setAge(int age) throws IllegalAgeException{
if (age < 0 || age > 100) {
//throw new RuntimeException("年龄不合法");
throw new IllegalAgeException("年龄不合法");
}
this.age = age;
}
}
package day08;
/**
* 测试异常的抛出
* @author xxx
*
*/
public class ExceptionDemo4 {
public static void main(String[] args){
Person p = new Person();
/*
* 当调用一个含有throws声明异常抛出的方法时,编译器要求必须处理该异常。
* 处理手段有两种:
* 1、使用try-catch捕获并处理。
* 2、在当前方法上继续使用throws声明该异常的抛出。但不要在main方法上抛异常,会被JVM杀掉当前进程退出。
*/
try {
p.setAge(20);
} catch (IllegalAgeException e) {
e.printStackTrace();
}
System.out.println("年龄为:"+p.getAge());
}
}
1.4 重写方法时的throws
如果使用继承时,在父类的某个方法上宣告了throws某些异常,而在子类别中重写该方法时,您可以:
1、不处理异常(重新定义时不设定throws);
2、可仅throws父类别中声明的部分异常;
3、可throws父类方法中抛出异常的子类异常。
但是不可以:
1、throws出额外的异常;
2、throws父类方法中抛出异常的父类异常。
二、RuntimeException
2.1 RuntimeException的特点
Java异常可分为可检测异常,非检测异常。
可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,不捕捉这个异常,编译器就通不过,不允许编译。
非检测异常不遵循处理或者声明规则,在产生此类异常时,不一定非要采取任何适当操作,编译器不会检查是否已经解决了这样一个异常。
RuntimeException类属于非检测异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现,因此它们不受编译器检查与处理或声明规则的限制。
2.2 常见RuntimeException
- IllegalArgumentException
抛出的异常表明向方法传递了一个不合法或不正确的参数。 - NullPointerException
当应用程序试图在需要对象的地方使用null时,抛出该异常。 - ArrayIndexOutOfBoundsException
当使用的数组下标超出数组允许范围时,抛出该异常。 - ClassCastException
当试图将对象强制转换为不是实例的子类时,抛出该异常。 - NumberFormatException
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
三、异常常用API
3.1 printStackTrace
void printStackTrace(),Throwable中定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容。
3.2 getMessage
String getMessage(),Throwable中定义了一个方法可以得到有关异常事件的信息。
package day08;
/**
* Exception常用用法
* @author xxx
*
*/
public class ExceptionDemo5 {
public static void main(String[] args) {
System.out.println("程序开始了");
try {
String str = "abc";
System.out.println(Integer.parseInt(str));
} catch (Exception e) {
//e.printStackTrace();
System.out.println(e.getMessage());
}
System.out.println("程序结束了");
}
}
四、自定义异常
创建自定义异常类,语法格式:
class [自定义异常类名] extends Exception{
…
}
当定义好自定义异常后,我们可以通过Eclipse来自动生成相应的构造方法。
package day08;
/**
* 年龄不合法异常
*
* 自定义异常,通常是用来描述某个业务逻辑上出现的问题。
* 自定义异常的名字应当做到见名知义
* @author xxx
*
*/
public class IllegalAgeException extends Exception{
private static final long serialVersionUID = 1L;
public IllegalAgeException() {
super();
}
public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public IllegalAgeException(String message, Throwable cause) {
super(message, cause);
}
public IllegalAgeException(String message) {
super(message);
}
public IllegalAgeException(Throwable cause) {
super(cause);
}
}
上面自定义的异常在前面的代码Person类中有应用到。