Java 7對抑制異常的支持

在JDK 7中 ,向Throwable類( Exception和Error類的父類)添加了一個新的構造函數和兩個新方法。 添加了新的構造函數和兩個新方法以支持“抑制的異常”(不要與吞咽或忽略異常的不良做法相混淆)。 在本文中,我將探討為什么引入這些方法以及它們在JDK 7中的使用方式。我簡短討論了抑制異常與鏈式異常的不同之處。

被抑制的異常在新的Java 7 try-with-resources語句 (也稱為自動資源管理 [ ARM ])的執行中起著重要作用。 為這種新的資源管理功能提供API支持似乎是Throwable類上新的構造函數和方法的主要驅動程序,它們提供對抑制的異常的訪問,但是API支持在try-with-resources語句之外使用抑制的異常。 。

遇到受抑制的異常的最常見用例是,當try-with-resources語句(這是一種嘗試類型,根據Java語言規范Java SE 7 Edition 14.20 ,它不需要catch或finally子句時)遇到一個異常。 try塊中的異常,然后在隱式嘗試關閉相關資源時遇到另一個異常。

為了說明這種情況,我組成了自己的“資源”,可以在try-with-resource語句中使用它,因為它實現了java.lang.AutoCloseable接口。 當使用它的代碼嘗試使用它時,此“頑皮資源”會故意引發異常,然后在調用重寫的close方法(由AutoCloseable接口指定的唯一方法)時引發另一個異常,從而繼續其不良形式。 接下來顯示NaughtyResource的代碼清單。

NaughtyResource.java

package dustin.examples;/*** Resource that throws exceptions both in its use and its closure and is only* intended for use in demonstrating Java 7's suppressed exceptions APIs. This* is not a well-behaved class.* * @author Dustin*/
public class NaughtyResource implements AutoCloseable
{/*** Method that intentionally throws an exception.* * @throws RuntimeException Thrown no matter how you call me.*/public void doNothingGood(){throw new RuntimeException("Nothing good can come of this.");}/*** The overridden closure method from AutoCloseable interface.* * @throws Exception Exception that might be thrown during closure of this*    resource.*/@Overridepublic void close() throws Exception{throw new UnsupportedOperationException("Not supported yet.");}
}

現在有了頑皮的資源,是時候使用頑皮的資源并演示抑制異常API。 下一張圖片描述了如果嘗試使用此資源而不捕獲close方法隱式拋出的Exception且未聲明該方法拋出該異常的情況,將發生什么情況。

這是javac提供的錯誤消息,如以下屏幕快照所示。

我已經顯示了前兩個屏幕快照,以強調對資源執行的隱式關閉調用。 NetBeans編輯器和控制臺中顯示的錯誤消息清楚地表明了這種情況。

下一個代碼清單包含編譯的SuppressedExceptions類的第一個版本。

SuppressedExceptions.java(版本1)

package dustin.examples;/*** Demonstrate JDK 7's Suppressed Exceptions API support.* * @author Dustin*/
public class SuppressedExceptions
{/*** Executable function demonstrating suppressed exceptions.* * @param arguments The command line arguments; none expected.*/public static void main(String[] arguments) throws Exception{try (NaughtyResource naughty = new NaughtyResource()){naughty.doNothingGood();}}
}

盡管在執行上述代碼時確實遇到了兩個異常(一個在NaughtyResource.doNothingGood()調用的try塊中,一個在隱式調用close方法的調用中),但只有一個滲透到頂部,并在應用程序顯示時顯示運行。 下一個屏幕快照對此進行了演示。

如最后一個圖像所示,僅顯示在try-with-resources語句的try try塊中遇到的異常。 在這里,可以向Throwable(在這種情況下為Exception)詢問其受抑制的異常的功能非常有用。 為了證明這一點,接下來顯示SuppressedExceptions類的版本2(使用Throwable.getSuppressed() )。

SuppressedExceptions.java(版本2)

package dustin.examples;import static java.lang.System.err;/*** Demonstrate JDK 7's Suppressed Exceptions API support.* * @author Dustin*/
public class SuppressedExceptions
{/*** Method that uses NaughtyResource with try-with-resource statement.* * @throws Exception Expected exception for try-with-resource used on the*    NaughtyResource.*/public static void performTryWithResource() throws Exception{try (NaughtyResource naughty = new NaughtyResource()){naughty.doNothingGood();}  }/*** Executable function demonstrating suppressed exceptions.* * @param arguments The command line arguments; none expected.*/public static void main(String[] arguments){try{performTryWithResource();}catch (Exception ex){err.println("Exception encountered: " + ex.toString());final Throwable[] suppressedExceptions = ex.getSuppressed();final int numSuppressed = suppressedExceptions.length;if (numSuppressed > 0){err.println("\tThere are " + numSuppressed + " suppressed exceptions:");for (final Throwable exception : suppressedExceptions){err.println("\t\t" + exception.toString());}}}}
}

上面的應用程序將打印出所有抑制的異常。 在這種情況下,嘗試關閉NaughtyResource時遇到的異常現在顯示為被抑制的異常之一。 下一個屏幕快照對此進行了演示。

如Java教程中所述,我們看到唯一拋出的異常是在try-with-resources語句的try塊中遇到的異常,并且在資源關閉期間遇到的第二個異常被“抑制”(但仍可從實際拋出異常)。

不需要使用try-with-resources來處理抑制的異常。 下一個代碼清單將SuppressedExceptions改編為使用更傳統的try-finally。

SuppressedExceptions.java(版本3)

package dustin.examples;import static java.lang.System.err;/*** Demonstrate JDK 7's Suppressed Exceptions API support.* * @author Dustin*/
public class SuppressedExceptions
{/*** Method that uses NaughtyResource with JDK 7 try-with-resource statement.* * @throws Exception Expected exception for try-with-resource used on the*    NaughtyResource.*/public static void performTryWithResource() throws Exception{try (NaughtyResource naughty = new NaughtyResource()){naughty.doNothingGood();}  }/*** Method that uses NaughtyResource with traditional try-finally statement.* * @throws Exception Exception thrown during use of NaughtyResource.*/public static void performTryFinally() throws Exception{final NaughtyResource naughty = new NaughtyResource();try{naughty.doNothingGood();}finally{naughty.close();}}/*** Executable function demonstrating suppressed exceptions.* * @param arguments The command line arguments; none expected.*/public static void main(String[] arguments){try{
//         performTryWithResource();performTryFinally();}catch (Exception ex){err.println("Exception encountered: " + ex.toString());final Throwable[] suppressedExceptions = ex.getSuppressed();final int numSuppressed = suppressedExceptions.length;if (numSuppressed > 0){err.println("\tThere are " + numSuppressed + " suppressed exceptions:");for (final Throwable exception : suppressedExceptions){err.println("\t\t" + exception.toString());}}else{err.println("\tNo Suppressed Exceptions.");}}}
}

上面的代碼調用了一種使用try-finally的方法,其行為與try-with-resources示例的行為不同,如下面的屏幕快照所示。

try-finally顯示嘗試關閉資源時遇到的異常,而不是使用資源時遇到的異常(上面顯示的try-with-resources相反)。 另一個不同之處是,即使在try-finally情況下,作為抑制的異常,其他異常也不可用。 這是一個廣為宣傳的 “ 丟失的異常 ”問題的示例 ,該問題可能包含潛在的“瑣碎”異常(關閉資源),而隱藏了潛在的更重要的異常(實際上是在使用資源)。

如果我想同時查看NaughtyResource的使用和關閉過程中引發的異常以及try-finally,可以使用Throwable.addSuppressed(Throwable) ,如下面的代碼清單所示。 在該清單中,對try和finally子句進行了增強,以捕獲使用NaughtyResource期間引發的異常,并將捕獲的異常添加到實際拋出的異常中作為抑制的異常。

SuppressedExceptions.java(版本4)

package dustin.examples;import static java.lang.System.err;/*** Demonstrate JDK 7's Suppressed Exceptions API support.* * @author Dustin*/
public class SuppressedExceptions
{/*** Method that uses NaughtyResource with JDK 7 try-with-resource statement.* * @throws Exception Expected exception for try-with-resource used on the*    NaughtyResource.*/public static void performTryWithResource() throws Exception{try (NaughtyResource naughty = new NaughtyResource()){naughty.doNothingGood();}  }/*** Method that uses NaughtyResource with traditional try-finally statement.* * @throws Exception Exception thrown during use of NaughtyResource.*/public static void performTryFinally() throws Exception{final NaughtyResource naughty = new NaughtyResource();Throwable throwable = null;try{naughty.doNothingGood();}catch (Exception usingEx){throwable = usingEx;}finally{try{naughty.close();}catch (Exception closingEx){if (throwable != null){closingEx.addSuppressed(throwable);throw closingEx;}}}}/*** Executable function demonstrating suppressed exceptions.* * @param arguments The command line arguments; none expected.*/public static void main(String[] arguments){try{
//         performTryWithResource();performTryFinally();}catch (Exception ex){err.println("Exception encountered: " + ex.toString());final Throwable[] suppressedExceptions = ex.getSuppressed();final int numSuppressed = suppressedExceptions.length;if (numSuppressed > 0){err.println("\tThere are " + numSuppressed + " suppressed exceptions:");for (final Throwable exception : suppressedExceptions){err.println("\t\t" + exception.toString());}}else{err.println("\tNo Suppressed Exceptions.");}}}
}

修改后的類的輸出如下所示。 注意,由于使用資源本身而導致的異常現在與作為抑制的異常而引發的異常相關聯。 盡管此處未顯示,但Throwable現在還提供了一個構造函數,該構造函數允許通過布爾參數指定新實例化的Throwable是否允許(啟用)抑制的異常(禁止)。

查看抑制異常的另一個角度是完整堆棧跟蹤。 以下三幅圖像是使用try-with-resources(顯式顯示假定的異常),使用傳統的try-finally語句而未顯式添加抑制的異常(因此在full stack跟蹤中沒有抑制的異常)導致的完整堆棧跟蹤的屏幕快照。 ,并使用傳統的try-finally方法,并明確添加抑制的異常(因此確實會出現在完整堆棧跟蹤中)。 我在每個圖像上都添加了一條紅線,以單獨顯示整個堆棧跟蹤結束的位置,并在適用的情況下,圈出了對抑制異常的顯式引用。

抑制的異常與鏈接的異常

禁止的異常與鏈接的異常不同 。 鏈接異常是JDK 1.4引入的,旨在使輕松跟蹤異常之間的因果關系成為可能。 通常,鏈接的異常是由于將新引發的異常與已捕獲并導致引發新異常的異常相關聯而導致的。 例如,可能會引發未檢查的異常,從而“包裝”已捕獲的已檢查的異常,并且可以將它們鏈接在一起。

JDK 7引入了抑制的異常,它與因果關系無關,而與在單個拋出的異常中表示可能相關但不一定因果的多個例外條件有關。 在上面的我的頑皮資源示例中,頑皮資源在其唯一方法被調用時的異常并不是導致它在調用其close方法時引發異常的原因。 因此,將兩個異常關聯起來(通過抑制的異常機制)比強迫一個異常似乎是造成連鎖關系中另一個異常的原因更有意義。

通過比較Throwable訪問每種類型的方法,最快速地了解鏈式異常與抑制型異常之間的區別可能是最容易的。 對于鏈式異常,將調用特定的Exception(Throwable)方法。 此方法返回導致Throwable的單個實例。 可以詢問返回的Throwable的原因,并在導致Throwables的整個過程中重復該過程。 重要的觀察結果是,每個給定的Throwable都有一個導致Throwable的原因。 這可以與Throwable在調用其getSuppressed()方法時提供多個抑制的Throwable(在數組中)的能力進行對比。

NetBeans推薦嘗試資源

在此值得注意的是,NetBeans會警告您嘗試使用try-finally,并建議使用try-with-resources替換它,如我在我的文章《 用于現代化Java代碼的七個NetBeans提示》和下面顯示的屏幕快照中所討論的。

結論

我相信很明顯,為什么NetBeans建議開發人員將對資源處理的最后嘗試更改為try-with-resources語句。 通常最好先了解資源上的哪個操作導致了異常,但是如果需要的話,也能夠在關閉時訪問異常是很不錯的。 如果必須選擇,我通常會對執行期間的資源問題更感興趣,因為關閉問題可能是該問題的衍生形式。 但是,兩者都更好。 傳統的try-finally最終僅列出關閉時的異常,而無需付出額外的努力來中繼這兩者。 try-with-resource語句不僅更簡潔; 由于內置支持包含抑制的異常,它也更加有用。

參考: JCG合作伙伴 Dustin Marx在Inspired by Actual Events博客上提供了Java 7對抑制異常的支持 。


翻譯自: https://www.javacodegeeks.com/2012/04/java-7s-support-for-suppressed.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/373171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373171.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux 如何做共享磁盤陣列,在Linux上玩轉磁盤陣列分享

大部分用戶都會擔心,萬一硬盤發生故障,一、使用磁盤陣列可以帶來哪些好處?在具體如何配置磁盤陣列之前,筆者要先給大家介紹一下利用磁盤陣列的好處。先給大家一點動力,讓大家能夠繼續看下面的內容。第一個好處是磁盤陣列可以提高…

my-innodb-heavy-4g.cnf

my-innodb-heavy-4g.cnf轉載于:https://www.cnblogs.com/xiluhua/p/6231834.html

易于使用的單位和集成代碼

此示例說明如何使用Maven和Sonar生成單元測試和集成測試的覆蓋率。 它使用非常簡單的技術,只需10-15分鐘即可在任何現有的Maven構建中運行。 它可用于單元,集成,ATDD或任何其他類型的測試套件。 覆蓋率結果顯示在Sonar中。 有什么事嗎&#x…

Dij的堆優化

#include<algorithm> #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define M 100000 #define pa pair<int,int>//優先比較第一個元素 using namespace std; int d[M],n,m,cnt,head[M],next[M],u[M],dis[M],n…

linux db2sysc 內存,db2sysc進程占用linux內存持續增長,請各位指點。

該服務器近期做過的變更情況&#xff1a;變更前&#xff0c;使用 sar -r 1 3 看內存使用率服務器內存使用率一直是70%該服務器原為獨立物理服務器&#xff0c;經過虛擬化遷移到EXS上成為虛擬服務器。遷移后發現swap無法啟動。原因是原物理服務器硬盤控制器為cciss。/etc/fstab …

k8s的探針

一、探針原理 分布式系統和微服務體系結構的挑戰之一是自動檢測不正常的應用程序&#xff0c;并將請求&#xff08;request&#xff09;重新路由到其他可用系統&#xff0c;恢復損壞的組件。健康檢查是應對該挑戰的一種可靠方法。使用 Kubernetes&#xff0c;可以通過探針配置運…

第一百三十節,JavaScript,封裝庫--連綴

JavaScript&#xff0c;封裝庫--連綴 學習要點&#xff1a; 1.連綴介紹 2.改寫庫對象 本章我們重點來介紹&#xff0c;在調用庫的時候&#xff0c;我們需要能夠在前臺調用的時候可以同時設置多個操作&#xff0c;比如設置CSS&#xff0c;設置innerHTML&#xff0c;設置click事件…

Spring3:類型安全依賴項注入

在從Spring跳到類型安全依賴注入之前&#xff0c;我想討論一下我們之前所做的方式。 我們一直在借助Spring的Autowired注釋按類型使用依賴項注入。 像這樣的東西會注入Spring Bean。 Autowired private StudentDao studentDao; // Autowires by type. Injects the instance who…

userData IE

蠻討厭IE的&#xff0c;因為他常常需要特別照顧&#xff0c;就像DOM Storage(sessionStorage和localStorage)只能支持IE8&#xff0c;對于以下的只能使用userData。 原理&#xff1a;通過在document元素后面附加一個專屬的“DHTML行為”來實現客戶端存儲&#xff0c; var memor…

context元素大概解說

Context元素代表一個web應用&#xff0c;運行在某個特定的虛擬主機上。如Servlet Specification 2.2或以后版本中描述的那樣&#xff0c;每個web應用基于一個Web Application Archive(WAR)文件&#xff0c;或者是一個目錄&#xff0c;包含WAR文件解壓后的內容。有關Web Applica…

全新的Play模塊資料庫

去年11月&#xff0c;我曾與Play框架的 Nicolas Leroux談過創建模塊存儲庫的問題。 他同意這將是一個好主意&#xff0c;但是時間不足使我無法開始。 在上周Google Play小組發生了暴風雨之后&#xff0c;我決定將其優先處理。 可以在幾周內提供可工作的原型。 概述&#xff1a;…

Ubuntu 16.04 安裝 VMware-Workstation-12

以前一直使用 Ubuntu Virtaulbox &#xff0c;最近測試了 VMware-Workstation-9,性能超過 Virtaulbox-4.2.x,下面是詳細步驟:1 首先準備一個Ubuntu 系統 lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 16.04 LTS Release: 16.04 …

Linux的md64進程,在Linux上安裝Elasticsearch Kibaba.md(示例代碼)

在Linux上安裝Elasticsearch KibabaKibana是一個開源為elasticsearch 引擎提供數據和數據分析1、下載安裝切換到root賬戶&#xff0c;按順序依次執行以下命令rpm包安裝$wget -c https://artifacts.elastic.co/downloads/kibana/kibana-5.5.3-x86_64.rpm$sha1sum kibana-5.3.2-x…

SSH實戰 · 唯唯樂購項目(中)

用戶模塊三&#xff1a;一級分類的查詢創建一級分類表并導入基本數據CREATE TABLE category (cid int(11) NOT NULL AUTO_INCREMENT,cname varchar(255) DEFAULT NULL,PRIMARY KEY (cid)) ENGINEInnoDB AUTO_INCREMENT11 DEFAULT CHARSETutf8;建包及相應的類:com.weiwei.shoppi…

播放2 –模塊,插件有什么區別?

關于Play 2模塊和插件似乎有些混亂。 我想這是因為兩者經常是同義詞。 在Play&#xff08;兩個版本-1和2&#xff09;中&#xff0c;存在明顯的差異。 在本文中&#xff0c;我將介紹什么是插件&#xff0c;如何在Java和Scala中實現插件&#xff0c;以及如何從模塊導入插件。 外…

Linux多線程貝葉斯建樹教程,建樹經驗.doc

建樹經驗分子進化樹構建及數據分析的簡介mediocrebeing, rodger, lylover, klaus, oldfish, yzwpf一、引言開始動筆寫這篇短文之前&#xff0c;我問自己&#xff0c;為什么要寫這樣的文章&#xff1f;寫這樣的文章有實際的意義嗎&#xff1f;我希望能夠解決什么樣的問題&#x…

Android的IPC機制(一)——AIDL的使用

綜述 IPC(interprocess communication)是指進程間通信&#xff0c;也就是在兩個進程間進行數據交互。不同的操作系統都有他們自己的一套IPC機制。例如在Linux操作系統中可以通過管道、信號量、消息隊列、內存共享、套接字等進行進程間通信。那么在Android系統中我們可以通過Bin…

python學習筆記(python介紹)

為什么要學python&#xff1f; python和shell的比較&#xff0c;和PHP、和JAVA比較 運維開發只是用到python的很小一部分 python在一些知名公司的應用&#xff1a; 谷歌&#xff1a;python的創始人原來在谷歌工作。 CIA&#xff1a;美國中情局網站用python開發的 NASA&#xff…

Netty:透明地使用SPDY和HTTP

大多數人已經從谷歌那里聽說過SPDY&#xff0c;該協議被提議作為老化的HTTP協議的替代品。 Web服務器是瀏覽器正在緩慢地實現該協議&#xff0c;并且支持正在增長。 在最近的文章中&#xff0c;我已經寫過SPDY的工作方式以及如何在Jetty中啟用SPDY支持。 由于Netty&#xff08;…

selenium 等待頁面加載完成

一、隱形加載等待&#xff1a; file:///C:/Users/leixiaoj/Desktop/test.html 該頁面負責創建一個div <html> <head><title>Set Timeout</title><style>.red_box {background-color: red; width 20%; height:100px; border: none;}</style&…