Java之异常
异常
抛出异常
- 所有标准异常类都有两个构造器:一个是默认构造器,另一个是接收字符串作为参数的构造器。
- 使用throw关键字来抛出异常对象。
- 可以抛出任何类型的Throwable对象,它是异常类型的根类。但是通常来说,我们对于不同异常还是抛出对应的异常比较好,可以方便其他人处理。
-
if (true) {throw new Throwable();}if (true) {throw new Exception("hello");}if (true) {throw new NullPointerException("空指针异常");}
- 异常说明:
- 定义:它属于方法声明的一部分,跟在形式参数列表之后。
- 作用:在明确会发送异常时,要么对异常进行处理,要么就使用异常说明,告知他人此方法将抛出异常,调用时需进行处理,他也可以选择处理还是继续向上抛出,如果最后被某个人处理了,那么就没问题,否则,程序会报出此异常。
- 用法:使用throws关键字加上所有潜在异常类型的列表。
- 可以只写一个异常类型来抛出所有可能的异常,就是Exception。
-
public void test() throws NullPointerException, IndexOutOfBoundsException {}
-
捕获异常
try块
- 作用:可以用来在方法内设置一个特殊的块去捕获异常。
- 用法:在try关键字后面跟一个代码块,将可能发生异常的代码放入其中。
-
try {//这里编写可能发生异常的代码}
异常处理
- 当try块抓到了异常,我们就必须得想办法处理,此时就该异常处理程序上场了。
- 异常处理程序是跟在try块后面的catch子句。
- catch子句:
- 用法:在catch关键字后面跟一个括号,再跟一个代码块,括号中是异常的对象及类型,代码块是编写怎么处理异常。
- catch子句可以有多个,多个子句分别用来处理try块中代码可能抛出的所有种类的异常。
- 当异常被抛出时,异常处理机制将查找参数与异常匹配的第一个处理程序,然后进入catch子句中执行。
- 可以使用Exception对象的printStackTrace()方法打印从方法调用到异常抛出的堆栈。
- 可以只写一个异常处理程序来捕获所有类型的异常,就是Exception,但是,最好把它放在最后,以防止前面有更具体的类型与异常相匹配。
- 捕获了异常时,也可以不处理,使用throw继续向外抛出。同时,你可以使用fillInStackTrace()方法将异常的发生地更新。
-
catch (Exception e) {throw e.fillInStackTrace();}
-
- 注:只有抛出的异常和catch声明的异常相匹配才会进入执行。
-
catch (Exception e) {//这里编写处理异常的代码}
使用finall清理
- 它是try是否会抓到异常都会执行的块。
- 它通常与用于关闭资源等。
- 使用:使用finally加一个代码块。
- 它要么跟在try块后,要么跟在最后一个catch子句后。
-
try {} catch (Exception e) {} finally {}try {} finally {}
-
- finally子句永远会得到执行。
-
try {System.out.println("try 1");if (true) {return;}System.out.println("try 2");} catch (Exception e) {} finally {System.out.println("finally 1");}输出:try 1finally 1
-
创建自定义异常
- 可以从已有的异常类进行继承,尽量选择意思相近的异常类,如果找不到就使用Exception。
- 所有异常的基类是Exception,Exception又是继承自Throwable类。
- Throwable:
- 可以调用以下方法打印堆栈信息。
-
try {throw new Throwable("MyException");} catch (Throwable e) {System.out.println("getMessage():" + e.getMessage());System.out.println("getLocalizedMessage():" + e.getLocalizedMessage());System.out.println("toString():" + e);System.out.println("printStackTrace():");e.printStackTrace(System.out);}输出:getMessage():MyExceptiongetLocalizedMessage():MyExceptiontoString():java.lang.Throwable: MyExceptionprintStackTrace():java.lang.Throwable: MyExceptionat com.eos.javalearn.JavaLearnClass.main(JavaLearnClass.java:886)
- 还可以使用getStackTrace()方法获取一个由栈轨迹中的元素所组成的数组,栈顶元素时异常抛出之处,栈底是第一个方法调用。获取之后可以打印每个元素的方法名、行号、所在文件的名字等等。
-
try {throw new Throwable("MyException");} catch (Throwable e) {for (StackTraceElement ele : e.getStackTrace()) {System.out.println(ele.getMethodName());System.out.println(ele.getFileName());System.out.println(ele.getLineNumber());System.out.println("-------------------------------");}}
-
-
class MyException extends Exception {public MyException() {}public MyException(String message) {super(message);}}public class JavaLearnClass {public void test() throws MyException {System.out.println("test()");throw new MyException();}public void test1() throws MyException {System.out.println("test1()");throw new MyException("自定义异常");}public static void main(String[] args) {JavaLearnClass javaLearnClass = new JavaLearnClass();try {javaLearnClass.test();} catch (MyException e) {System.out.println("捕获住了MyException异常!");e.printStackTrace();}try {javaLearnClass.test1();} catch (MyException e) {System.out.println("捕获住了MyException异常!");e.printStackTrace();}}}输出:test()捕获住了MyException异常!test1()捕获住了MyException异常!com.eos.javalearn.MyExceptionat com.eos.javalearn.JavaLearnClass.test(JavaLearnClass.java:857)at com.eos.javalearn.JavaLearnClass.main(JavaLearnClass.java:869)com.eos.javalearn.MyException: 自定义异常at com.eos.javalearn.JavaLearnClass.test1(JavaLearnClass.java:862)at com.eos.javalearn.JavaLearnClass.main(JavaLearnClass.java:875)
异常丢失
- ①在finally中使用return,导致异常丢失;
- 如下:finally里进行了return,如果没有这个return,throw抛出的异常将会被打印出来,但是加了return之后则不会打印。
-
try {System.out.println("try 1");if (true) {throw new RuntimeException();}System.out.println("try 2");} finally {System.out.println("finally 1");return;}输出:try 1finally 1
- ②异常被抑制:
- 如下:在finally中抛出了另一个异常,如果不抛出该异常时,try中的异常会正常打印,但是加上了之后则只会打印新的异常,try的异常将丢失。
-
try {System.out.println("try 1");if (true) {throw new RuntimeException();}System.out.println("try 2");} finally {System.out.println("finally 1");throw new NullPointerException();}输出:try 1finally 1java.lang.NullPointerExceptionat com.eos.javalearn.JavaLearnClass.main(JavaLearnClass.java:906)
- ③只捕获异常但不处理:
- 如下:你进行了异常捕获,但是catch中没有任何处理或者打印异常的堆栈,导致异常发生时看不到任何信息。等于说是你把这个异常给私吞了,在你或他人遇到遇到问题时,只能看见异常现象,但是想通过log查看异常信息时却没有任何打印,这是要极力避免的。
-
try {throw new RuntimeException();} catch (Exception e) {}
-
- 如下:你进行了异常捕获,但是catch中没有任何处理或者打印异常的堆栈,导致异常发生时看不到任何信息。等于说是你把这个异常给私吞了,在你或他人遇到遇到问题时,只能看见异常现象,但是想通过log查看异常信息时却没有任何打印,这是要极力避免的。