如何處理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

可以嘗試著寫一個(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)越常見嫌蚤,這樣就不可避免的會(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)系作者
  • 序言:七十年代末憔足,一起剝皮案震驚了整個(gè)濱河市胁附,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滓彰,老刑警劉巖控妻,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異揭绑,居然都是意外死亡弓候,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門他匪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)菇存,“玉大人,你說(shuō)我怎么就攤上這事诚纸∽辏” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵畦徘,是天一觀的道長(zhǎng)毕籽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)井辆,這世上最難降的妖魔是什么关筒? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮杯缺,結(jié)果婚禮上蒸播,老公的妹妹穿的比我還像新娘。我一直安慰自己萍肆,他們只是感情好袍榆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著塘揣,像睡著了一般包雀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上亲铡,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天才写,我揣著相機(jī)與錄音,去河邊找鬼奖蔓。 笑死赞草,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吆鹤。 我是一名探鬼主播厨疙,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼疑务!你這毒婦竟也來(lái)了轰异?” 一聲冷哼從身側(cè)響起岖沛,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搭独,沒(méi)想到半個(gè)月后婴削,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡牙肝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年唉俗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片配椭。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡虫溜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出股缸,到底是詐尸還是另有隱情衡楞,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布敦姻,位于F島的核電站瘾境,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏镰惦。R本人自食惡果不足惜迷守,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旺入。 院中可真熱鬧兑凿,春花似錦、人聲如沸茵瘾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拗秘。三九已至卓嫂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間聘殖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工行瑞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奸腺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓血久,卻偏偏與公主長(zhǎng)得像突照,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子氧吐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容