如何處理Java 中的Checked Exception

想必很多人對(duì)JAVA中的Exception不會(huì)陌生,但是我們也會(huì)碰到諸多的Checked Exception。而我們又不想一層層去捕獲,那么就需要想辦法來(lái)忽略這些Checked Exception。

那么何為Checked Exception, 何為Unchecked Exception。


所示

正如上圖中所示:

  • Checked Exception: 指的是不能恢復(fù),必須要被使用者來(lái)處理的一類異常,如果不捕獲,那么編譯會(huì)報(bào)錯(cuò)。例如,IOException。
  • Unchecked Exception: 指的是在運(yùn)行時(shí)才會(huì)導(dǎo)致程序奔潰的異常,編譯時(shí)候并不會(huì)報(bào)錯(cuò)。例如,Runtime Exception。

如果在代碼中處處來(lái)處理Checked Exception,那么代碼就會(huì)變成冗長(zhǎng)并且可讀性變差,所以在某些情況下需要對(duì)其進(jìn)行處理,變成Unchecked Exception。

1. try catch

最簡(jiǎn)單的方案之一就是使用try catch然后在捕獲到checked exception之后拋出Unchecked Exception。

例如:

public DbConnection getDbConnection(String username, String password) {

    try {
        return new DbProvider().getConnect(username, password);
    } catch (IOException e) {
        throw new RuntimeException();
    }
  }

這樣的處理邏輯到處都會(huì)用到,代碼也會(huì)顯得冗長(zhǎng),降低了可讀性。

2. 一個(gè)通用的Wrapper

可以嘗試著寫(xiě)一個(gè)通用的Wrapper,統(tǒng)一處理類似的Checked Exception。

  • 我們需要把上述代碼中的new DbProvider().getConnect(username, password);包裝成一個(gè)通用的接口RuntimeExceptionWrappable

    public interface RuntimeExceptionWrappable<T> {
    T execute() throws IOException;
    }

  • 接下來(lái)可以替換原有代碼中的new DbProvider().getConnect(username, password);:

      RuntimeExceptionWrappable<DbConnection> wrappable = new RuntimeExceptionWrappable<DbConnection>() {
    
          @Override
          public DbConnection execute() throws IOException {
              return new DbProvider().getConnect(username, password);
          }
      };
    
  • 原有代碼的邏輯現(xiàn)在就變成下面的形式:

      RuntimeExceptionWrappable<DbConnection> wrappable = new RuntimeExceptionWrappable<DbConnection>() {
    
          @Override
          public DbConnection execute() throws IOException {
              return new DbProvider().getConnect(username, password);
          }
      };
    
      try {
          return wrappable.execute();
      } catch (IOException e) {
          throw new RuntimeException();
      }
    
  • 到目前為止,我們依然沒(méi)有把try catch去掉。我們接著把try catch部分提取出來(lái):

public class RuntimeExceptionWrapper {

    public static <T> T wrap(RuntimeExceptionWrappable<T> wrappable) {
        try {
            return wrappable.execute();
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }
}
  • 最后一步,完成整個(gè)代碼:
    RuntimeExceptionWrappable<DbConnection> wrappable = new RuntimeExceptionWrappable<DbConnection>() {

        @Override
        public DbConnection execute() throws IOException {
            return new DbProvider().getConnect(username, password);
        }
    };

    return RuntimeExceptionWrapper.wrap(wrappable);

到這里就可以看到,Wrapper被抽象到獨(dú)立的類中了。

3. Stream中的Exception

自從JAVA8依賴,流處理在代碼中已經(jīng)變得越來(lái)越常見(jiàn),這樣就不可避免的會(huì)有Exception出現(xiàn)在Stream流處理中。

public class UrlHandler {

    public List<URL> getURLs() {
        return Stream.of("http://www.baidu.com", "https://www.google.com")
            .map(this:createURL)
            .collect(Collectors.toList());
    }

    private URL createURL(String url) throws MalformedURLException {
        return new URL(url);
    }
}

上述代碼是編譯不通過(guò)的,原因是createURL拋出了Checked Exception。只有對(duì)stream流處理進(jìn)行修改,接收Exception代碼才能編譯:

public List<URL> getURLs() {
    return Stream.of("http://www.baidu.com", "https://www.google.com")
            .map(url -> {
                try {
                    return this.createURL(url);
                } catch (MalformedURLException e) {
                    throw new RuntimeException();
                }
            })
            .collect(Collectors.toList());
}

這段代碼雖然能夠工作,但是依然顯得不是很優(yōu)雅。還是跟前一部分一樣,我們抽取出來(lái)一個(gè)通用的Wrapper。

  • 首先將this.createURL提取出來(lái),作為一個(gè)通用的接口,由于createURL是一個(gè)函數(shù),所以接口形式如下:
@FunctionalInterface
public interface RuntimeWrappableFunction<T, R> {
    R apply(T t) throws Exception;
}
  • 接下來(lái),由于map的參數(shù)是一個(gè)函數(shù)式接口,所以我們來(lái)完成一個(gè)消費(fèi)上述函數(shù)接口的實(shí)現(xiàn):
public class RuntimeWrappableFunctionMapper {
    public static <T, R> Function<T, R> wrap(RuntimeWrappableFunction<T, R> wrappableFunction) {
        return t -> {
            try {
                return wrappableFunction.apply(t);
            } catch (Exception e) {
                throw new RuntimeException();
            }
        };
    }
}
  • 完善原有的代碼:
public class UrlHandler {

    public List<URL> getURLs() {
        return Stream.of("http://www.baidu.com", "https://www.google.com")
            .map(RuntimeWrappableFunctionMapper.wrap(this::createURL))
            .collect(Collectors.toList());
}

    private URL createURL(String url) throws MalformedURLException {
        return new URL(url);
    }
}
  • 有一些可選的庫(kù)也可以完成上述的功能。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容