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 1 finally 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():MyException getLocalizedMessage():MyException toString():java.lang.Throwable: MyException printStackTrace(): java.lang.Throwable: MyException at 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.MyException at 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 1 finally 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 1 finally 1 java.lang.NullPointerException at com.eos.javalearn.JavaLearnClass.main(JavaLearnClass.java:906)
- ③只捕获异常但不处理:
- 如下:你进行了异常捕获,但是catch中没有任何处理或者打印异常的堆栈,导致异常发生时看不到任何信息。等于说是你把这个异常给私吞了,在你或他人遇到遇到问题时,只能看见异常现象,但是想通过log查看异常信息时却没有任何打印,这是要极力避免的。
-
try { throw new RuntimeException(); } catch (Exception e) { }
-
- 如下:你进行了异常捕获,但是catch中没有任何处理或者打印异常的堆栈,导致异常发生时看不到任何信息。等于说是你把这个异常给私吞了,在你或他人遇到遇到问题时,只能看见异常现象,但是想通过log查看异常信息时却没有任何打印,这是要极力避免的。