Throwable
所有异常类的超类
Error
严重的异常,比如加载大量图片的时候内存会溢出,就属于严重异常,可以使用第三方框架ImageLoader去加载图片。
Exception
分为编译时期异常和运行时期异常;
编译时期异常:只要出现的不是运行时期异常,统称为编译时期异常。
如:ParseException,String转换Date时解析错误。
编译时期异常必须进行处理否则无法通过编译。
运行时期异常:RuntimeException,可以通过编译但是代码不严谨。
如:NullPointerExceptino空指针异常
处理异常
throws
直接将异常抛出。对于编译时期的异常如果不做异常处理编译就无法通过,执行该异常处理后,当发生异常时会将异常类显示在控制台上。
throws表示可能会发生异常,有些方法中自带了异常就必须抛出才能编译通过
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Except {
public static void main(String[] args) throws ParseException {
//抛出ParseException异常,但不代表该异常一定会发生
SimpleDateFormat adf=new SimpleDateFormat("yy-MM-dd");
Date d=new Date();
d=adf.parse("2018:12:30");//输入了不正确的格式
System.out.println(d);
}
}
/**
Exception in thread "main" java.text.ParseException: Unparseable date: "2018:12:30"
at java.base/java.text.DateFormat.parse(Unknown Source)
at ExceptDemo.Except.main(Except.java:12)
*/
注意事项:
子类继承父类的时候的注意事项
- 子类重写父类的方法的时候,子类的方法的抛出的异常必须和父类的方法异常一样,要么是父类方法异常的子类
- 子类重写父类方法的时候,如果父类中的这个方法没有抛出异常,那么子类重写的这个方法也不能抛出异常,只能try...catch
throw
表示抛出一个异常对象,用匿名内部类的方式
throws | throw | |
功能 | 抛出异常,它后面跟的异常类名,并且可以多个异常类名中间逗号开 | 抛出的一个异常对象 |
位置 | 在方法上抛出,由调用者处理 | 在语句体中抛出的,由语句体进行处理 |
确定性 | 表示的是出现异常的可能性 | 表示抛出异常的肯定性 |
public class Except {
public static void main(String[] args) {
int a = 10;
int b = 0;
if(b==0) {
throw new ArithmeticException();//匿名内部类的方式跟一个异常对象
}else {
System.out.println(a / b);// 除数为0
}
System.out.println("程序结束");
}
}
/**
Exception in thread "main" java.lang.ArithmeticException
at ExceptDemo.Except.main(Except.java:8)
*/
try...catch...finally
异常捕获机制,try中的代码如果发生异常就会显示catch中的异常提醒。
finally为对异常的处理,finally中的代码一定会执行。用于解决异常,比如数据库的回滚操作。
final | 修饰类,该类不能被继承;修饰变量,该变量是常量;修饰成员方法,该方法无法重写 |
finalize | 运行垃圾回收器gc(),实际是调用finalize()方法,和垃圾回收器有关系 |
finally | 在io,数据库中以及后面对数据库操作(DBUtuls/c3p0/Hibernate/MyBatis)里面中释放资源的 |
解决一个异常
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Except {
public static void main(String[] args){
SimpleDateFormat adf = new SimpleDateFormat("yyyy-MM-dd");
Date d = new Date();
try {
d = adf.parse("2008:5:20");// 输入了不正确的格式
} catch (ParseException e) {
e.printStackTrace();//直接通过异常类对象将异常显示在控制台
}
System.out.println(d);
}
}
/**
java.text.ParseException: Unparseable date: "2008:12:30"
at java.base/java.text.DateFormat.parse(Unknown Source)
at ExceptDemo.Except.main(Except.java:12)
Fri May 18 22:14:19 CST 2018
*/
可以看出来try...catch异常处理方式并不会直接终止程序,而是在发生异常的位置在控制台显示异常。程序跳过了异常部分直接打印了当前的时间。
注意
- 编译器中可以通过shift+alt+z快速给选中的代码添加try...catch异常处理
- try中的代码应当越少越好。
- catch中可以直接抛出异常也可以确切的说明异常。
解决多个异常
对于一段代码中有多个异常可以使用一个try多个catch的方式处理,应当将范围大的异常放在下面。
public class Except {
public static void main(String[] args) {
int a = 10;
int b = 0;
int[] arr = { 1, 2, 3 };
try {
System.out.println(a / b);// 除数为0
System.out.println(arr[3]);// 脚标越界
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("数组脚标越界");
} catch (ArithmeticException e) {
System.err.println("除数不能为0");
} catch (Exception e) {//最大的异常放在最下面
System.err.println("程序出现问题");
}
System.out.println("程序结束");
}
}
/**
除数不能为0
程序结束
*/
这种处理方式当try中的代码出现问题只会抛出遇到的第一个异常,然后跳过try中的代码继续执行程序。
JDK 7以后新增的方式
可以在一个catch中通过 | 分隔添加多个异常,注意添加的异常是同一级别的。
public class Except {
public static void main(String[] args) {
int a = 10;
int b = 0;
int[] arr = { 1, 2, 3 };
try {
System.out.println(a / b);// 除数为0
System.out.println(arr[3]);// 脚标越界
} catch (ArrayIndexOutOfBoundsException | ArithmeticException e) {
System.out.println("程序出现问题了");
} finally {
// finally中的代码一定会执行,除非在这之前JVM退出了
System.out.println("这里通常用于释放资源");
}
System.out.println("程序结束");
}
}
/**
程序出现问题了
这里通常用于释放资源
程序结束
*/
如果在方法中catch中存在return的问题
public class Except {
public static void main(String[] args) {
System.out.println(get());
}
public static int get() {
int a = 10;
int b = 0;
try {
System.out.println(a/b);
} catch (Exception e) {
a=30;
System.out.println("catch");
return a;
}finally {
a=40;
System.out.println("finally");
}
return a;
}
}
/**
catch
finally
30
*/
虽然finally中的方法一定会执行,从例题中看出输出了finally说明finally中的代码执行了,但是finally是在catch之后执行的,在catch中已经记录了返回值为30,程序在记录了返回值为30后再执行了finally中的方法。所以最终的结果是30。
自己定义异常类
import java.util.Scanner;
class MyException extends Exception {
// 定义一个自定义异常类,继承自Exception
public MyException() {
super();
}
// 使用构造方法定义异常
public MyException(String message) {
super(message);
}
}
class Teacher {
// 校验学生成绩的功能
public void check(int score) throws MyException {
// 方法上要抛出异常
if (score < 0 || score > 100) {
// 抛出异常类的对象
throw new MyException("该学生成绩不符合...");
} else {
System.out.println("该学生成绩没有问题");
}
}
}
public class Except {
public static void main(String[] args) throws MyException {
// 创建键盘录入对象
Scanner sc = new Scanner(System.in);
// 接收数据
System.out.println("请输入学生成绩:");
int score = sc.nextInt();
Teacher t = new Teacher();
t.check(score);// 执行带异常处理的方法
}
}
/**
请输入学生成绩:
200
Exception in thread "main" ExceptDemo.MyException: 该学生成绩不符合...
at ExceptDemo.Teacher.check(Except.java:24)
at ExceptDemo.Except.main(Except.java:40)
*/