目录
异常:
将程序的出现的问题封装了类,就形成了异常类。
Throwable抽象类是异常类的根类:Error类和Exception类是Throwable抽象类的子类。
Throwable抽象类:
Error:(程序出现的错误,不能使用程序处理,一般无需程序员关注)
Exception:
编译时异常:不处理会报错,必须处理(无法预估的用户操作) ------------ 处理方式有两种:捕获 + 抛出
运行时异常: 处不处理都可以,一般是代码写的有问题,自己找问题并修改。
处理异常的目的: 让代码能够继续运行下去。捕获 + 抛出 二者配合使用:一般在内层抛出,在外层捕获统一处理。
异常信息是以多线程的方式输出的,因此多条信息的顺序可能在二次输出的时候产生不一致。
异常的处理方式:
捕获 ----------------- try…catch(){} 与 try…catch…finally 两种形式
格式: try{
//可能出现异常的代码
}catch(异常类名 对象名){
//对异常的处理
}finally{
//一定会执行的代码 ---------- finally块通常用来做资源释放操作:关闭文件,关闭数据库连接等等
}
抛出 ------------------ 向上抛给方法的调用者,最终抛给JVM。而JVM的默认处理方式终止程序,打印异常信息。
格式:在方法头上: throws 异常类名1,类名2 { ... }
异常的常用方法:
Throwable抽象类下的方法:
getMessage() ------------------------------------------- 获取异常信息,返回字符串。
toString() ------------------------------------------------- 获取异常类名和异常信息,返回字符串。
printStackTrace() -------------------------------------- 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
printStackTrace(PrintStream s) ------------------- 通常用该方法将异常内容保存在日志文件中,以便查阅。
public class ExceptionDemo {
public static void main(String[] args) {
try {
System.out.println(1/0);
} catch (Exception e) {
System.out.println(e.getMessage()); ///by zero
System.out.println(e.toString()); //java.lang.ArithmeticException: / by zero
/**
* java.lang.ArithmeticException: / by zero
* at com._51doit.javase05.day15.exceptiondemo.ExceptionDemo.main(ExceptionDemo.java:14)
*/
e.printStackTrace();
try {
e.printStackTrace(new PrintStream("d:/error.txt")); //若路径存在文件夹,则需手动创建
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}finally {
System.out.println("异常处理完毕!");
}
}
}
自定义异常:throw的用法
throw不是用来处理异常的,相反是生成一个异常,或者理解成引爆一个异常
格式: 方法名() { throw 异常对象 } ------------------------------------- throw的异常一定会发生,并且
public class ExceptionDemo02 {
public static void main(String[] args) {
try {
test();
} catch (Exception e) {
e.printStackTrace(); //java.lang.NullPointerException
}
System.out.println("over");
}
private static void test() throws Exception { //抛给上层调用者:main方法
//一定会产生,此处调用了父类Exception中的有参构造方法
throw new NullPointerException("这个异常是有我创J的");
}
}
自定义异常:
定义编译时异常: 继承Exception
定义运行时异常: 继承RuntimeException
//继承Exception属于编译时异常,必须要做出处理
public class MyException extends Exception{
public MyException() {} //无参构造
public MyException(String desc) {
//对父类Exception的构造方法进行传参,好处是可以在异常信息输出时将字符串的内容打印出来
super(desc);
}
}
public class ExceptionDemo03 {
public static void main(String[] args) { //一般在main()方法处进行捕获
Person p = new Person();
try {
p.setAge(200); //可能有异常的代码
} catch (MyException e) {
e.printStackTrace(); //获取异常类名和异常信息,以及异常出现在程序中的位置
}
}
}
class Person{
int age;
public void setAge(int age) throws MyException { //将异常返回给上层调用处main()
if(age<0 | age>150) {
throw new MyException("您的年龄超出正常范围!");
}
this.age = age;
}
public int getAge() {
return age;
}
}
异常的注意事项:
子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。
如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常。
如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws。
以上异常指的都是编译时异常。
- catch 块中可以存在多个,并且可以有子父类的关系。一旦存在子父类的关系,要把子类异常放上面,因为放下面,就再也执行不到了。catch块中应该写的是一种备选方案
- jdk7:一个catch块中可以处理多个异常,多个异常之间使用 | 隔开
- try块中的局部变量和catch块中的局部变量(包括异常变量),以及finally中的局部变量,他们之间不可共享使用。
- 每一个catch块用于处理一个异常。异常匹配是按照catch块的顺序从上往下寻找的,只有第一个匹配的catch会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义。
- 当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。
- finally块不管异常是否发生,只要对应的try执行了,则它一定也执行。只有一种方法让finally块不执行:System.exit()。因此finally块通常用来做资源释放操作:关闭文件,关闭数据库连接等等。