异常
异常是指在程序执行过程中的出现的非正常现象
一个良好的程序应该具备预见并处理可能发生的各种异常情况。
因此我们利用异常处理技术,来提高程序的容错能力
异常处理体系
检查异常也称为编译时异常。
不检查异常也称运行时异常。
Error类
表示程序无法恢复的严重错误或者恢复起来比较麻烦的错误,例如内存溢出、动态链接失败等等。
应用程序不主动抛出这些错误,通常由虚拟机自动抛出。
出现这种错误,最好的处理方式是让程序安全退出。
Exception类
由Java抛出和处理的非严重错误,
Exception的不同子类对应不同类型的异常
不受检异常(运行时异常)
包括RuntinmeException及其子类
!!还有error类及子类
受检异常
除了不受检异常外,其他继承自Exception类的异常。对于这些代码要求在代码中进行处理(可以try -- catch或者继续抛出异常直到到JVM自动处理)
常见的一些异常
3.运行时异常(不受检异常)
4.非运行时异常(受检异常)
两种查看异常信息的方法
public static void main(String[] args) { int a = 1; int b = 0; try { System.out.println(a/b); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } }
1.异常对象.getMessage()
此方法有返回值,返回报错信息
//上面的异常调用getMessage()打印下面 / by zero
2.异常对象.printStcakTrace()
没有返回值打印堆栈信息
// 打印结果如下 java.lang.ArithmeticException: / by zero at code.test.Demo0830.abnormal.demo.main(demo.java:9)
捕获异常
// 基本格式 try{ //可能出现异常的代码 } catch(异常类名 变量名) { // 异常处理 } finally { //最后执行的代码 //不管catch是否执行,finally都会执行 }
-
try-catch
-
try-catch-finally
-
try-catch-...-catch-finally
注意有return时的情况
public static void main(String[] args) { test(); } public static void test() { try { System.out.println("异常前"); System.out.println(1/0); System.out.println("异常后"); } catch (Exception e) { System.out.println(e.getMessage()); } finally { System.out.println("这里是finally"); } } //结果为 //异常前 // / by zero // 这里是finally
public static void main(String[] args) { test(); } public static void test() { try { System.out.println("异常前"); System.out.println(1/0); System.out.println("异常后"); return; } catch (Exception e) { System.out.println(e.getMessage()); } finally { System.out.println("这里是finally"); } } // 执行结果和上面的一样
总结一下
-
try的代码先执行,遇见异常进入catch,后进入finally(即使没有异常,finally也会执行)
抛出异常
1.throws声明抛出异常
public class ejection { public static void main(String[] args) { try { test(); } catch (Exception e) { System.out.println("你的异常信息是"+ e.getMessage()); System.out.println("我稳稳接住你的异常"); } } public static void test() throws Exception { System.out.println("我就想抛出异常"); System.out.println(1/0); } }
2.使用throw抛出异常
public class ejection1 { public static void main(String[] args) { try { test(); } catch (Exception e) { System.out.println("我稳稳接住你的异常"); System.out.println("你的异常是"+e.getMessage()); } } public static void test() throws Exception { throw new Exception("我就想抛出一个异常"); } }
自定义异常
自定义异常类
public class MyNoneExpection extends Exception{ MyNoneExpection(String message) { super(message); } }
public class demo { public static void main(String[] args) { try { throw new MyNoneExpection("我就主动抛出异常"); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } }
异常链
public static void main(String[] args) { try { Test3(); } catch (Exception e) { System.out.println(e.getMessage()); } } public static void Test1() throws MyNoneExpection { throw new MyNoneExpection("我是Test1的异常"); } public static void Test2() throws Exception { try { Test1(); } catch (Exception e) { throw new Exception("我是Test2的异常"); } } public static void Test3() throws Exception { try { Test2(); } catch (Exception e) { throw new Exception("我是Test3的异常"); } } //此程序 只能看到 我是Test3的异常 // 我们想要看到全部信息
解决方法一
抛出异常时Exception的重载方法
public static void main(String[] args) { try { Test3(); } catch (Exception e) { e.printStackTrace(); } } public static void Test1() throws MyNoneExpection { throw new MyNoneExpection("我是Test1的异常"); } public static void Test2() throws Exception { try { Test1(); } catch (Exception e) { throw new Exception("我是Test2的异常",e); } } public static void Test3() throws Exception { try { Test2(); } catch (Exception e) { throw new Exception("我是Test3的异常",e); } } /*java.lang.Exception: 我是Test3的异常 at code.test.Demo0830.abnormal.chain.Test3(chain.java:50) at code.test.Demo0830.abnormal.chain.main(chain.java:21) Caused by: java.lang.Exception: 我是Test2的异常 at code.test.Demo0830.abnormal.chain.Test2(chain.java:40) at code.test.Demo0830.abnormal.chain.Test3(chain.java:46) ... 1 more Caused by: code.test.Demo0830.abnormal.MyNoneExpection: 我是Test1的异常 at code.test.Demo0830.abnormal.chain.Test1(chain.java:31) at code.test.Demo0830.abnormal.chain.Test2(chain.java:36) ... 2 more*/
方法二 先接受上次的异常信息,然后通过异常类变量.initCause(异常对象) 将异常对象添加到一个异常对象中
public static void main(String[] args) { try { Test3(); } catch (Exception e) { e.printStackTrace(); } } public static void Test1() throws MyNoneExpection { throw new MyNoneExpection("我是Test1的异常"); } public static void Test2() throws Exception { try { Test1(); } catch (Exception e) { Exception e1 = e; e1.initCause(e); throw new Exception("我是Test2的异常",e1); } } public static void Test3() throws Exception { try { Test2(); } catch (Exception e) { Exception e1 = e; e1.initCause(e); throw new Exception("我是Test3的异常",e1); } } /*java.lang.Exception: 我是Test3的异常 at code.test.Demo0830.abnormal.chain.Test3(chain.java:50) at code.test.Demo0830.abnormal.chain.main(chain.java:21) Caused by: java.lang.Exception: 我是Test2的异常 at code.test.Demo0830.abnormal.chain.Test2(chain.java:40) at code.test.Demo0830.abnormal.chain.Test3(chain.java:46) ... 1 more Caused by: code.test.Demo0830.abnormal.MyNoneExpection: 我是Test1的异常 at code.test.Demo0830.abnormal.chain.Test1(chain.java:31) at code.test.Demo0830.abnormal.chain.Test2(chain.java:36) ... 2 more*/
getCause()方法
此方法返回上次异常的信息
public static void main(String[] args) { try { Test3(); } catch (Exception e) { e.getCause().printStackTrace(); } } public static void Test1() throws MyNoneExpection { throw new MyNoneExpection("我是Test1的异常"); } public static void Test2() throws Exception { try { Test1(); } catch (Exception e) { Exception e1 = e; e1.initCause(e); throw new Exception("我是Test2的异常",e1); } } public static void Test3() throws Exception { try { Test2(); } catch (Exception e) { Exception e1 = e; e1.initCause(e); throw new Exception("我是Test3的异常",e1); } } /*java.lang.IllegalArgumentException: Self-causation not permitted at java.base/java.lang.Throwable.initCause(Throwable.java:465) at code.test.Demo0830.abnormal.chain1.Test2(chain1.java:28) at code.test.Demo0830.abnormal.chain1.Test3(chain1.java:35) at code.test.Demo0830.abnormal.chain1.main(chain1.java:8) Caused by: code.test.Demo0830.abnormal.MyNoneExpection: 我是Test1的异常 at code.test.Demo0830.abnormal.chain1.Test1(chain1.java:18) at code.test.Demo0830.abnormal.chain1.Test2(chain1.java:23) ... 2 more