Java 异常

异常

+-------------------------------+
|	Throwable		|
|	/		        |
|      /	 	        |
|  Error	Exception	|
|                /      	|
|		/        	|
|	    Runtime	Other	|
+-------------------------------+
  • Runtime Exception是unchecked未受检异常,Other是checked检查异常。通常在程序中处理的都是受检异常。

  • Exception类是应该被程序捕获处理的;而Error同样也可以被捕获,但通常是JVM出现异常,这些严重的问题程序不应该捕获。所以不能直接捕获Throwable,而应该具体到Exception类。

受检异常和非受检异常

  1. 受检异常 Other Exception

    Java 在编译时就验证受检异常。 因此我们需要抛出或者捕获处理这些异常。

    常见的受检异常有IOExceptionSQLExceptionParseException

    我们可以通过继承 Exception 类来实现自定义的受检异常

  2. 非受检异常 Runtime Exception

    Java 不会在编译时验证非经受检的异常。这类异常通常反映了程序逻辑的一些错误。

    不受检我们也就不用捕获和抛出,但是运行时如果有错将会抛出异常。

    常见的是是 NullPointerExceptionArrayIndexOutOfBoundsExceptionIllegalArgumentExceptionArithmeticException

    我们可以通过继承 RuntimeException 来实现自定义的非受检异常

  • 什么时候使用受检异常,什么时候使用非受检异常?

    “如果可以合理地期望客户端从异常中恢复,请将其设为已检查的异常。 如果客户端无法从异常中恢复,请将其设为非经检查的异常。” -Oracle

try-with-source

java7引入,我们可以在try后括号内声明和初始化资源,执行完try块资源将自动关闭。

  1. 资源必须实现了AutoCloseable或Closeable接口
  2. 要自动关闭,必须在括号内声明和初始化资源
  3. 可以声明多个资源,用分号分隔
  4. 先声明的资源先初始化,但最后关闭

全局异常捕获

自从1.5开始,Java 的 Thread 类中提供了 UncaughtExceptionHandler 接口。

    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        void uncaughtException(Thread t, Throwable e);
    }

    // null unless explicitly set
    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(
                new RuntimePermission("setDefaultUncaughtExceptionHandler")
                    );
        }

         defaultUncaughtExceptionHandler = eh;
     }

要使用java提供的全局异常处理,我们需要实现一个 UncaughtExceptionHandler 的 Handler 类,并实现 uncaughtException 方法,该线程非被捕获的异常都将在这里处理,通常我们进行日志记录。然后线程有一个 defaultUncaughtExceptionHandler 属性,我们要将其设置为我们实现的 Handler 类。看看具体怎么做:

  public class Test {

      public static void main(String[] args) {

          Handler globalExceptionHandler = new Handler();
          Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
          System.out.println(10/0);
      }
  }

  class Handler implements Thread.UncaughtExceptionHandler {

      private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);

      public void uncaughtException(Thread t, Throwable e) {
          LOGGER.info("Unhandled exception caught!");
      }
  }

Runtime异常都可以被捕获,受检异常也可以抛出给它处理。

不过,这打破了就近捕获和处理异常的规则,在很多框架中都使用了全局异常。

原文地址:https://www.cnblogs.com/cpcpp/p/15261315.html