日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 架構(gòu)師社區(qū)
[導(dǎo)讀]來自:Java建設(shè)者 在 Java 中的基本理念是 結(jié)構(gòu)不佳的代碼不能運(yùn)行,發(fā)現(xiàn)錯誤的理想時期是在編譯期間,因?yàn)槟悴挥眠\(yùn)行程序,只是憑借著對 Java 基本理念的理解就能發(fā)現(xiàn)問題。但是編譯期并不能找出所有的問題,有一些 NullPointerException 和 ClassNotFoundEx

ce.com" data-mpa-powered-by="yiban.io">

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

來自:Java建設(shè)者


在 Java 中的基本理念是 結(jié)構(gòu)不佳的代碼不能運(yùn)行,發(fā)現(xiàn)錯誤的理想時期是在編譯期間,因?yàn)槟悴挥眠\(yùn)行程序,只是憑借著對 Java 基本理念的理解就能發(fā)現(xiàn)問題。但是編譯期并不能找出所有的問題,有一些 NullPointerException 和 ClassNotFoundException 在編譯期找不到,這些異常是 RuntimeException 運(yùn)行時異常,這些異常往往在運(yùn)行時才能被發(fā)現(xiàn)。

我們寫 Java 程序經(jīng)常會出現(xiàn)兩種問題,一種是 java.lang.Exception ,一種是 java.lang.Error,都用來表示出現(xiàn)了異常情況,下面就針對這兩種概念進(jìn)行理解。

認(rèn)識 Exception

Exception 位于 java.lang 包下,它是一種頂級接口,繼承于 Throwable 類,Exception 類及其子類都是 Throwable 的組成條件,是程序出現(xiàn)的合理情況。

在認(rèn)識 Exception 之前,有必要先了解一下什么是 Throwable。

什么是 Throwable

Throwable 類是 Java 語言中所有錯誤(errors)異常(exceptions)的父類。只有繼承于 Throwable 的類或者其子類才能夠被拋出,還有一種方式是帶有 Java 中的 @throw 注解的類也可以拋出。

在Java規(guī)范中,對非受查異常和受查異常的定義是這樣的:

The unchecked exception classes are the run-time exception classes and the error classes.

The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are Throwable and all its subclasses other than RuntimeException and its subclasses and Errorand its subclasses.

也就是說,除了 RuntimeException 和其子類,以及error和其子類,其它的所有異常都是 checkedException。

那么,按照這種邏輯關(guān)系,我們可以對 Throwable 及其子類進(jìn)行歸類分析

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

可以看到,Throwable 位于異常和錯誤的最頂層,我們查看 Throwable 類中發(fā)現(xiàn)它的方法和屬性有很多,我們只討論其中幾個比較常用的

// 返回拋出異常的詳細(xì)信息
public string getMessage();
public string getLocalizedMessage();

//返回異常發(fā)生時的簡要描述
public public String toString();
  
// 打印異常信息到標(biāo)準(zhǔn)輸出流上
public void printStackTrace()
;
public void printStackTrace(PrintStream s);
public void printStackTrace(PrintWriter s)

// 記錄棧幀的的當(dāng)前狀態(tài)
public synchronized Throwable fillInStackTrace()
;

此外,因?yàn)?Throwable 的父類也是 Object,所以常用的方法還有繼承其父類的getClass()getName() 方法。

常見的 Exception

下面我們回到 Exception 的探討上來,現(xiàn)在你知道了 Exception 的父類是 Throwable,并且 Exception 有兩種異常,一種是 RuntimeException ;一種是 CheckedException,這兩種異常都應(yīng)該去捕獲。

下面列出了一些 Java 中常見的異常及其分類,這塊面試官也可能讓你舉出幾個常見的異常情況并將其分類

RuntimeException

序號 異常名稱 異常描述
1 ArrayIndexOutOfBoundsException 數(shù)組越界異常
2 NullPointerException 空指針異常
3 IllegalArgumentException 非法參數(shù)異常
4 NegativeArraySizeException 數(shù)組長度為負(fù)異常
5 IllegalStateException 非法狀態(tài)異常
6 ClassCastException 類型轉(zhuǎn)換異常

UncheckedException

序號 異常名稱 異常描述
1 NoSuchFieldException 表示該類沒有指定名稱拋出來的異常
2 NoSuchMethodException 表示該類沒有指定方法拋出來的異常
3 IllegalAccessException 不允許訪問某個類的異常
4 ClassNotFoundException 類沒有找到拋出異常

與 Exception 有關(guān)的 Java 關(guān)鍵字

那么 Java 中是如何處理這些異常的呢?在 Java 中有這幾個關(guān)鍵字 throws、throw、try、finally、catch 下面我們分別來探討一下

throws 和 throw

在 Java 中,異常也就是一個對象,它能夠被程序員自定義拋出或者應(yīng)用程序拋出,必須借助于 throwsthrow 語句來定義拋出異常。

throws 和 throw 通常是成對出現(xiàn)的,例如

static void cacheException() throws Exception{

  throw new Exception();

}

throw 語句用在方法體內(nèi),表示拋出異常,由方法體內(nèi)的語句處理。throws 語句用在方法聲明后面,表示再拋出異常,由該方法的調(diào)用者來處理。

throws 主要是聲明這個方法會拋出這種類型的異常,使它的調(diào)用者知道要捕獲這個異常。throw 是具體向外拋異常的動作,所以它是拋出一個異常實(shí)例。

try 、finally 、catch

這三個關(guān)鍵字主要有下面幾種組合方式 try...catch 、try...finally、try...catch...finally。

try...catch 表示對某一段代碼可能拋出異常進(jìn)行的捕獲,如下

static void cacheException() throws Exception{

  try {
    System.out.println("1");
  }catch (Exception e){
    e.printStackTrace();
  }

}

try...finally 表示對一段代碼不管執(zhí)行情況如何,都會走 finally 中的代碼

static void cacheException() throws Exception{
  for (int i = 0; i < 5; i++) {
    System.out.println("enter: i=" + i);
    try {
      System.out.println("execute: i=" + i);
      continue;
    } finally {
      System.out.println("leave: i=" + i);
    }
  }
}

try...catch...finally 也是一樣的,表示對異常捕獲后,再走 finally 中的代碼邏輯。

JDK1.7 使用 try...with...resources 優(yōu)雅關(guān)閉資源

Java 類庫中有許多資源需要通過 close 方法進(jìn)行關(guān)閉。比如 InputStream、OutputStream,數(shù)據(jù)庫連接對象 Connection,MyBatis 中的 SqlSession 會話等。作為開發(fā)人員經(jīng)常會忽略掉資源的關(guān)閉方法,導(dǎo)致內(nèi)存泄漏。

根據(jù)經(jīng)驗(yàn),try-finally語句是確保資源會被關(guān)閉的最佳方法,就算異?;蛘叻祷匾惨粯?。try-catch-finally 一般是這樣來用的

static String firstLineOfFile(String path) throws IOException {
  BufferedReader br = new BufferedReader(new FileReader(path));
  try {
    return br.readLine();
  }finally {
    br.close();
  }
}

這樣看起來代碼還是比較整潔,但是當(dāng)我們添加第二個需要關(guān)閉的資源的時候,就像下面這樣

static void copy(String src,String dst) throws Exception{
        InputStream is = new FileInputStream(src);
  try {

    OutputStream os = new FileOutputStream(dst);
    try {
      byte[] buf = new byte[100];
      int n;
      while ((n = is.read()) >= 0){
        os.write(buf,n,0);
      }
    }finally {
      os.close();
    }
  }finally {
    is.close();
  }
}

這樣感覺這個方法已經(jīng)變得臃腫起來了。

而且這種寫法也存在諸多問題,即使 try - finally 能夠正確關(guān)閉資源,但是它不能阻止異常的拋出,因?yàn)?try 和 finally 塊中都可能有異常的發(fā)生。

比如說你正在讀取的時候硬盤損壞,這個時候你就無法讀取文件和關(guān)閉資源了,此時會拋出兩個異常。但是在這種情況下,第二個異常會抹掉第一個異常。在異常堆棧中也無法找到第一個異常的記錄,怎么辦,難道像這樣來捕捉異常么?

static void tryThrowException(String path) throws Exception {

  BufferedReader br = new BufferedReader(new FileReader(path));
  try {
    String s = br.readLine();
    System.out.println("s = " + s);

  }catch (Exception e){
    e.printStackTrace();
  }finally {
    try {
      br.close();
    }catch (Exception e){
      e.printStackTrace();
    }finally {
      br.close();
    }
  }
}

這種寫法,雖然能解決異常拋出的問題,但是各種 try-cath-finally 的嵌套會讓代碼變得非常臃腫。

Java7 中引入了try-with-resources 語句時,所有這些問題都能得到解決。要使用 try-with-resources 語句,首先要實(shí)現(xiàn) AutoCloseable 接口,此接口包含了單個返回的 close 方法。Java 類庫與三方類庫中的許多類和接口,現(xiàn)在都實(shí)現(xiàn)或者擴(kuò)展了 AutoCloseable 接口。如果編寫了一個類,它代表的是必須關(guān)閉的資源,那么這個類應(yīng)該實(shí)現(xiàn) AutoCloseable 接口。

java 引入了 try-with-resources 聲明,將 try-catch-finally 簡化為 try-catch,這其實(shí)是一種語法糖,在編譯時會進(jìn)行轉(zhuǎn)化為 try-catch-finally 語句。

下面是使用 try-with-resources 的第一個范例

/**
     * 使用try-with-resources 改寫示例一
     * @param path
     * @return
     * @throws IOException
     */

static String firstLineOfFileAutoClose(String path) throws IOException {

  try(BufferedReader br = new BufferedReader(new FileReader(path))){
    return br.readLine();
  }
}

使用 try-with-resources 改寫程序的第二個示例

static void copyAutoClose(String src,String dst) throws IOException{

  try(InputStream in = new FileInputStream(src);
      OutputStream os = new FileOutputStream(dst)){
    byte[] buf = new byte[1000];
    int n;
    while ((n = in.read(buf)) >= 0){
      os.write(buf,0,n);
    }
  }
}

使用 try-with-resources 不僅使代碼變得通俗易懂,也更容易診斷。以firstLineOfFileAutoClose方法為例,如果調(diào)用 readLine()close() 方法都拋出異常,后一個異常就會被禁止,以保留第一個異常。(公號回復(fù) 高效 即可領(lǐng)取 Effective Java 第三版中文 pdf)

異常處理的原則

我們在日常處理異常的代碼中,應(yīng)該遵循三個原則

  • 不要捕獲類似 Exception 之類的異常,而應(yīng)該捕獲類似特定的異常,比如 InterruptedException ,方便排查問題,而且也能夠讓其他人接手你的代碼時,會減少罵你的次數(shù)。
  • 不要生吞異常。這是異常處理中要特別注重的事情。如果我們不把異常拋出來,或者也沒有輸出到 Logger 日志中,程序可能會在后面以不可控的方式結(jié)束。
  • 不要在函數(shù)式編程中使用 checkedException 。

什么是 Error

Error 是程序無法處理的錯誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問題。大多數(shù)錯誤與代碼編寫者執(zhí)行的操作無關(guān),而表示代碼運(yùn)行時 JVM(Java 虛擬機(jī))出現(xiàn)的問題。這些錯誤是不可檢查的,因?yàn)樗鼈冊趹?yīng)用程序的控制和處理能力之 外,而且絕大多數(shù)是程序運(yùn)行時不允許出現(xiàn)的狀況,比如 OutOfMemoryErrorStackOverflowError異常的出現(xiàn)會有幾種情況,這里需要先介紹一下 Java 內(nèi)存模型 JDK1.7。

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

其中包括兩部分,由所有線程共享的數(shù)據(jù)區(qū)和線程隔離的數(shù)據(jù)區(qū)組成,在上面的 Java 內(nèi)存模型中,只有程序計(jì)數(shù)器是不會發(fā)生 OutOfMemoryError 情況的區(qū)域,程序計(jì)數(shù)器控制著計(jì)算機(jī)指令的分支、循環(huán)、跳轉(zhuǎn)、異常處理和線程恢復(fù),并且程序計(jì)數(shù)器是每個線程私有的。

什么是線程私有:表示的就是各條線程之間互不影響,獨(dú)立存儲的內(nèi)存區(qū)域。

如果應(yīng)用程序執(zhí)行的是 Java 方法,那么這個計(jì)數(shù)器記錄的就是虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是 Native 方法,這個計(jì)數(shù)器值則為空(Undefined)

除了程序計(jì)數(shù)器外,其他區(qū)域:方法區(qū)(Method Area)、虛擬機(jī)棧(VM Stack)、本地方法棧(Native Method Stack)堆(Heap) 都是可能發(fā)生 OutOfMemoryError 的區(qū)域。

  • 虛擬機(jī)棧:如果線程請求的棧深度大于虛擬機(jī)棧所允許的深度,將會出現(xiàn) StackOverflowError 異常;如果虛擬機(jī)動態(tài)擴(kuò)展無法申請到足夠的內(nèi)存,將出現(xiàn) OutOfMemoryError

  • 本地方法棧和虛擬機(jī)棧一樣

  • 堆:Java 堆可以處于物理上不連續(xù),邏輯上連續(xù),就像我們的磁盤空間一樣,如果堆中沒有內(nèi)存完成實(shí)例分配,并且堆無法擴(kuò)展時,將會拋出 OutOfMemoryError。

  • 方法區(qū):方法區(qū)無法滿足內(nèi)存分配需求時,將拋出 OutOfMemoryError 異常。

一道經(jīng)典的面試題

一道非常經(jīng)典的面試題,NoClassDefFoundError 和 ClassNotFoundException 有什么區(qū)別?

在類的加載過程中, JVM 或者 ClassLoader 無法找到對應(yīng)的類時,都可能會引起這兩種異常/錯誤,由于不同的 ClassLoader 會從不同的地方加載類,有時是錯誤的 CLASSPATH 類路徑導(dǎo)致的這類錯誤,有時是某個庫的 jar 包缺失引發(fā)這類錯誤。NoClassDefFoundError 表示這個類在編譯時期存在,但是在運(yùn)行時卻找不到此類,有時靜態(tài)初始化塊也會導(dǎo)致 NoClassDefFoundError 錯誤。

ClassLoader 是類路徑裝載器,在Java 中,類路徑裝載器一共有三種兩類

一種是虛擬機(jī)自帶的 ClassLoader,分為三種

  • 啟動類加載器(Bootstrap) ,負(fù)責(zé)加載 $JAVAHOME/jre/lib/rt.jar
  • 擴(kuò)展類加載器(Extension) ,負(fù)責(zé)加載 $JAVAHOME/jre/lib/ext/*.jar
  • 應(yīng)用程序類加載器(AppClassLoader) ,加載當(dāng)前應(yīng)用的 classpath 的所有類

第二種是用戶自定義類加載器

  • Java.lang.ClassLoader 的子類,用戶可以定制類的加載方式。

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

另一方面,ClassNotFoundException 與編譯時期無關(guān),當(dāng)你嘗試在運(yùn)行時使用反射加載類時,ClassNotFoundException 就會出現(xiàn)。

簡而言之,ClassNotFoundException 和 NoClassDefFoundError 都是由 CLASSPATH 中缺少類引起的,通常是由于缺少 JAR 文件而引起的,但是如果 JVM 認(rèn)為應(yīng)用運(yùn)行時找不到相應(yīng)的引用,就會拋出 NoClassDefFoundError 錯誤;當(dāng)你在代碼中顯示的加載類比如 Class.forName() 調(diào)用時卻沒有找到相應(yīng)的類,就會拋出 java.lang.ClassNotFoundException。

  • NoClassDefFoundError 是 JVM 引起的錯誤,是 unchecked,未經(jīng)檢查的。因此不會使用 try-catch 或者 finally 語句塊;另外,ClassNotFoundException 是受檢異常,因此需要 try-catch 語句塊或者 try-finally 語句塊包圍,否則會導(dǎo)致編譯錯誤。
  • 調(diào)用 Class.forName()、ClassLoader.findClass() 和 ClassLoader.loadClass() 等方法時可能會引起 java.lang.ClassNotFoundException ,如圖所示

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

  • NoClassDefFoundError 是鏈接錯誤,發(fā)生在鏈接階段,當(dāng)解析引用找不到對應(yīng)的類,就會觸發(fā);而 ClassNotFoundException 是發(fā)生在運(yùn)行時的異常。
文章參考:

https://www.java67.com/2012/12/noclassdeffounderror-vs-classnotfoundexception-java.html

《極客時間-Java核心技術(shù) 36 講》

《深入理解 Java 虛擬機(jī)》第二版

《Effective Java 第三版》

https://www.cnblogs.com/xiohao/p/3547443.html

https://blog.csdn.net/qq_29229567/article/details/80773970

https://blog.csdn.net/riemann_/article/details/87522352

《Java編程思想》

https://www.cnblogs.com/xz816111/p/8466048.html

https://docs.oracle.com/javase/specs/jls/se9/html/jls-11.html#jls-11.1.1

jdk 1.8 源碼注釋

特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

長按訂閱更多精彩▼

看完這篇Exception 和 Error,和面試官扯皮就沒問題了

ce: normal;text-align: right;line-height: 2em;box-sizing: border-box !important;word-wrap: break-word !important;">如有收獲,點(diǎn)個在看,誠摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計(jì)中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機(jī)驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計(jì)工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉