摘要:java异常指在程序运行时可能出现的一些错误,如:文件找不到、网络链接失败、非法参数等。异常是一个事件,它发生在程序运行期间,中断了正在执行的程序的正常指令流。
本文分享自华为云社区《Java知识点问题精选之异常机制》,原文做者:breakDraw 。java
java异常指在程序运行时可能出现的一些错误,如:文件找不到、网络链接失败、非法参数等。异常是一个事件,它发生在程序运行期间,中断了正在执行的程序的正常指令流。程序员
Java经过API中Throwable类的众多子类描述各类不一样的异常。于是,Java异常都是对象,是Throwable子类的实例,描述了出如今一段编码中的错误条件。当条件生成时,错误将引起异常。对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不一样。segmentfault
Q: Throwable 和 Error的关系
A: Throwable是Error(错误)的基类,也是Exception的基类
1个好图,可看到常见的异常和error网络
Q: Error和Exception的关系
A:jvm
Q: Error能够被catch捕捉吗?
A: 只要是Throwable和其子类都是能够throw和catch的。 可是不建议捕捉Error。ide
异常体系还能够分为这2类:编码
Q: return-finally陷阱1: finally能经过修改变量,来更新return的变量值吗spa
int f() { int a = 1; try { return a; } finally { a=2; } }
A: 不能, f返回1。线程
Q: return-finally陷阱2: finally里也return时,返回哪一个?code
int f() { try { return 1; } finally { return 2; } }
A:返回finally里的,返回2。
Q: 什么状况下finally块里的步骤能够不执行?
A: 只有在finally以前调用System.exit(0)退出jvm, 才能让finally不执行。
Q: 下面会发生什么?
try { start(); } catch (Exception ex) { System.out.println("catch Exception"); } catch (RuntimeException re) { System.out.println("catch RuntimeException"); }
A: 直接编译就错误了。 catch是会按顺序的且匹配1个就再也不往下匹配,编译器所以识别出RuntimeExcpetion永远不会被捕捉到,便提早报错。
Q:throw异常的时候,在finally中作return,那么异常还会抛出吗?
static int f() { try { int a = 1/0; return a; } catch (Exception e) { throw new RuntimeException(e); } finally { return -1; } } public static void main(String[] args) { System.out.println(f()); }
A:不会,返回-1.
即finaly中作return会中断throw
所以永远不要在finally中去作return操做
Q: 子类覆写基类方法时 , 能throws基类方法中不存在的异常吗?
像下面这样:
class A{ void f() throws IOException{ } } class B extends A{ void f() throws IOException, SQLException { } }
A: 不行,直接编译报错。 即子类覆写父类方法时, throws关键字后面跟的异常必须是小于等于父类方法异常的。
Q: finally中调用某资源的close时,也会抛出受检异常, 除了在finally里作try-catch,还能怎么作?
像下面这样,finally又有catch,就很难看:
TryWithResource tryWithResource = new TryWithResource(); try { System.out.println(tryWithResource.age); } catch (Exception e) { e.printStackTrace(); }finally { try { tryWithResource.close(); } catch (Exception e) { e.printStackTrace(); } }
A:若是是JDK1.7,能够用try-with-resource语法。
须要资源类实现AutoCloseable接口, 并在try的时候在try括号后面跟上资源的建立,以下:
public static void main(String[] args) { try (TryWithResource tryWithResource = new TryWithResource()) { System.out.println(tryWithResource.age); } catch (Exception e) { e.printStackTrace(); } }
这样就不须要写finally,finally+close会经过编译器给咱们自动加上。
Q: 线程抛出异常的话该怎么捕捉?
A: 实现异常处理接口MyUnchecckedExceptionhandler
public class MyUnchecckedExceptionhandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("捕获异常处理方法:" + e); } }
而后把实现类设置给对应线程。
Thread t = new Thread(new ExceptionThread()); t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler()); t.start();