日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

异常--------JavaSE

發布時間:2023/12/8 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异常--------JavaSE 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

StringBuilder sb=new StringBuider();

sb.append("123");

sb.append("456");

這個過程中始終都是stringBuilder對象

運行時異常: 程序運行的時候才出現的異常,什么空指針異常,數組越界,用try catch

非運行時異常:沒有運行的時候編譯時期程序就會報錯,有紅線,用try catch捕獲或者throws聲明

防御式編程:

LBYL:在操作之前就做出了充分的檢查

EAFP:先操作,遇到問題再進行處理

在我們的Java中,將程序執行過程中發生的不正常行為稱為異常,Java不同類型的異常,都有對應的類來進行描述,程序發生異常本質上是new了一個異常對象然后拋出去,在由我們的程序和JVM處理

異常的概念和體系結構

1.Throwable:是我們異常體系的頂層類,這樣就派生出兩個重要的子類,Error和Exception

在Java中,所有的異常類型都是java.lang.Throwable的子類,在Throwable下面有兩個異常的分支,一個是Exception一個是error;

2.Error:指的是Java虛擬機都無法進行解決的嚴重問題,JVM內部錯誤

指的是java運行時的內部錯誤和資源耗盡錯誤,應用程序不會拋出此類異常,這種內部錯誤一旦出現,除了告知用戶程序終止之外,其他的也無能為力,例如堆棧溢出是這種錯誤的一例StackOverflowError

3.Exception:異常產生后端程序員可以通過代碼來進行處理

Exception異常的一個分類:

1)運行時異常(非受查異常)

都是 RuntimeException 類及其子類異常,例如NullPointerException,ClassNotFoundException,IndexOutOfBoundsException,ArithmeticException他是點擊運行程序之后拋出的異常,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般由程序邏輯錯誤引起,程序應該從邏輯角度盡可能避免這類異常的發生。

2)非運行時異常(受查異常)---編譯時期異常

他是在程序進行編譯的時候就會發生的異常,我們必須在程序運行之前進行處理,例如 IOExceptionClassNotFoundException,CloneNotSupportedException,classCastException

但是IOException又可以分為EOFException,FileNotFoundException

注意:我們的編譯時候出現的語法錯誤,是不可以稱之為異常,比如說System.out.println寫錯了,這是在編譯期出錯,而運行是指程序已經編譯通過了得到class文件了,再有JVM執行出現的錯誤

異常的拋出

在我們進行編寫程序的時候,如果我們的程序發生了錯誤,用戶不想處理這個異常,那么我們此時就要將錯誤的信息告訴提醒方法調用者來進行處理

在我們的Java中,我們可以通過throw關鍵字,拋出一個指定的異常對象,將錯誤信息告訴調用者:

throw new XXXException("異常產生的原因");

1)throw必須寫在方法內部
2)拋出的對象必須是Exception或者是Exception的子類對象
3)如果拋出的是RunTimeException或者是RunTimeException的子類,那么可以不用處理,直接交給JVM處理
4)拋出的是編譯時異常,用戶必須進行處理,否則無法通過編譯
5)異常一旦進行拋出,后面的代碼就不會執行

2.異常的捕獲:

異常的捕獲,就是異常的具體處理方式,主要有兩種:異常聲明throws以及try catch進行捕獲處理

異常的聲明:

try語句塊中存放的是可能出現異常的代碼

catch語句塊中存放的是出現異常之后的處理行為

finally語句塊的代碼用于處理善后工作,常常在最后執行

用try catch來進行捕獲異常

try代碼塊中放的是可能出現異常的代碼,catch代碼塊中存放的是出現異常后的處理行為,finally是用于代碼塊的善后處理工作,一般是在最后面執行;

1,不進行處理異常,就發現程序會終止在出現異常的地方,后面不會再繼續執行,因為程序會把異常直接交給JVM來進行處理,這樣的處理結果是,程序會拋出異常,并且不會再繼續向下執行int[] arr1={1,2,3};System.out.println(arr1[0]);System.out.println(arr1[3]);System.out.println("hello"); 2,但是此時當程序進行用try catch來進行包裹異常的時候程序會自己在catch中處理異常 這樣處理的結果是程序會自動向下執行,但是一旦try中發現異常的語句,就會立即跳到catch語句里面 try之后代碼塊的語句不會執行,catch執行完畢之后會繼續向下自動執行,程序并不會終止int[] arr1={1,2,3};try{System.out.println(arr1[0]);System.out.println(arr1[4]);//程序執行到這里,立即跳轉到catch語句System.out.println("我愛我的家");}catch(ArrayIndexOutOfBoundsException e) //這里面的ArrayIndexOutOfBoundsException不可以換成其他的異常,否則還是會交給JVM進行處理{}System.out.println("我愛我的祖國"); 最終我們打印的結果是1,我愛我的祖國

finally中的代碼手機一定會被執行的,所以我們會優先執行finally中的return語句

catch也可以有多個,finally常常用于最后的善后工作,例如釋放資源,無論是否發生異常,finally的代碼塊最終一定會被調用到,一旦異常類型不匹配,catch是不可以進行捕獲的

int[] arr1={1,2,3,4,5,6,7};try{arr1=null;System.out.println("hehe");System.out.println(arr1[5]);System.out.println("heihei");}catch(ArrayIndexOutOfBoundsException e){e.printStackTrace();System.out.println("此時發生了數組越界異常·");}catch (NullPointerException e){e.printStackTrace();System.out.println("此時發生了空指針異常");} 最終打印結果的值是hehe,此時發生了空指針異常

1)或者這么寫:多個異常還可以同時進行捕獲

try{語句塊}catch(異常1|異常2 e){

}?

2)我們在進行捕獲異常的時候,catch語句塊捕獲最好是從上向下是子類--->父類

不要寫成父類--->子類

Scanner scanner=new Scanner(System.in);try{int num= scanner.nextInt();System.out.println(10/num);}catch(InputMismatchException e){e.printStackTrace();System.out.println("輸入錯誤");}catch (ArithmeticException e){e.printStackTrace();System.out.println("算數異常,可能0作為了除數");}finally{scanner.close();System.out.println("finally代碼塊最終執行了");} 0 算數異常,可能0作為了除數 finally代碼塊最終執行了

示例代碼:用try回收資源

try(Scanner scanner=new Scanner(System.in)){int num= scanner.nextInt();System.out.println(10/num); }catch(InputMismatchException e) {System.out.println("此時發生了輸入錯誤"); }catch(ArithmeticException e) {System.out.println("此事發生了算數異常,可能0作為了分母"); }}

如果此方法中沒有合適的處理異常的方式,就會沿著調用棧向上進行傳遞

public static void func(int n){System.out.println(10/n);}public static void main(String[] args) {try{func(0);}catch(ArithmeticException e){System.out.println("此時發生了算數異常");}} 最終交給了main函數來進行處理

但是如果說一直向上傳遞都沒有合適的方法去處理異常(main函數里面都沒有try Catch)那么最終就會交給JVM來進行處理(和我們最開始沒有使用try catch是一樣的)

public static void func(int n){System.out.println(10/n);}public static void main(String[] args) {func(0);System.out.println(123);} 這個程序最終什么結果都不會進行打印,咱們的func處理不了這個異常,J就會向上傳遞,讓main方法來進行處理,此時main方法也沒有辦法處理這個異常,那么直接交給JVM來進行處理,程序會終止public static int func(){int a=10;try{return a;}catch(ArithmeticException e){e.printStackTrace();}finally{System.out.println("1");return 20;}}public static void main(String[] args) {int num=func();System.out.println(num);} 最終打印結果是1 20,此時異常有func方法交給了main方法,main方法捕獲了這個異常并進行了處理

下面我們來進行總結:

1)程序會先進行執行try中的代碼

2)如果try中的代碼出現了異常,就會結束try中的代碼,看看是否與catch中的異常類型是否匹配,如果不能進行匹配,那么就會直接交給JVM來進行處理

3)如果沒有找到匹配的異常類型,就會沿著異常信息調用棧異常向上傳遞到上層調用者;

4)無論是否找到匹配的異常類型,finally中的代碼都會被執行掉,(在該方法結束之前執行)

5)如果上層調用者也沒有處理了的異常,就會繼續執行向上傳遞,一旦main()方法也沒有合適的代碼處理異常,就會交給JVM來進行處理,此時代碼就會異常終止;

2.手動拋出異常

public static int func(int x){if(x==0){throw new ArithmeticException("hh");}return 1;//return x/10;}public static void main(String[] args) {int x=func(0);System.out.println(x);} 無論返回多少,程序啥都不會進行打印public static void main(String[] args) {throw new ArithmeticException("111");}int x=0;if(x==0){throw new UnsupportedOperationException("x==0我是不允許的");}

?3.處理受查異常:所謂的受檢異常,表示在編譯的時候強制檢查的異常,這種異常需要顯示的通過try/catch來捕捉,或者通過throws拋出去,否則從程序無法通過編譯。

當一個代碼中出現了受查異常,必須顯式進行處理,如果一段代碼可能會出現受查異常,那么也需要進行處理;

public static void main(String[] args) throws FileNotFoundException {File file=new File("d:/22");Scanner scanner=new Scanner(file);System.out.println(scanner.nextLine());}

1)使用try catch進行包裹

public static String readFile() {Scanner scan=null;try{File file=new File("d:/22");scan=new Scanner(file);}catch(FileNotFoundException e){e.printStackTrace();}return scan.nextLine();}public static void main(String[] args) {String str=readFile();System.out.println(str);}

2)在方法名后面加上異常說明,相當于將處理動作交給上級調用者

public static String readFile() throws FileNotFoundException {File file=new File("d:/22");Scanner scanner=new Scanner(file);return scanner.nextLine();}public static void main(String[] args) throws FileNotFoundException {String str=readFile();}

4.自定義異常

一個自定義異常繼承了Exception就被稱為受查異常,繼承于RuntimeException就被稱為非受查異常

static class MyException extends Exception{ public MyException(String message) { super(message); //不提供構造方法默認就是用不帶有參數的 } } static class MyException1 extends RuntimeExceptionpublic MyException1(String message) { super(message); } } public static void func1(int x){ if(x==0) { try { throw new MyException("這是我自己拋出的異常"); //也可以在方法后面加上MyException驗證異常調用棧交給向上處理} catch (MyException e) { e.printStackTrace(); } } } public static void func2(int x) { if(x==0){ throw new MyException1("x==0");//不需要進行try catch進行包裹 } }

實例1:實現一個簡單的用戶登錄功能

static class NameException extends RuntimeException{public NameException(String message){super(message);}}static class PasswordException extends RuntimeException{public PasswordException(String message){super(message);}}private static final String name="李佳偉";private static final String password="12503487";public static void login(String name, String password) throws NameException, PasswordException {if(!test.name.equals(name)){throw new NameException("您輸入的用戶名錯誤");}if(!test.password.equals(password)){throw new PasswordException("您輸入的密碼是錯誤的");}System.out.println("登陸成功");}public static void main(String[] args) {try {login("李佳偉","12503487");} catch (NameException e) {e.printStackTrace();} catch (PasswordException e) {e.printStackTrace();}}

示例2:使用while循環來進行類似于恢復異常的處理行為,它將不斷重復,直到程序不在拋出異常

public static void main(String[] args) {int i = 0;while (i < 15) {try {if (i < 10) {throw new UnsupportedOperationException("i現在還小于10");}} catch (UnsupportedOperationException e) {e.printStackTrace();System.out.println("第" + i + "次");i++;}}}

1)Final關鍵字有什么作用?

1)使用final修飾的類,就不能被其他類繼承了,表示此類設計得很完美,不需要進行被修改和擴展

2)final修飾的方法表示不允許此類繼承的類重寫該方法,表示此方法提供的功能已經滿足當前需求,不需要進行擴展

3)final修飾變量的時候,表示該屬性一旦被初始化之后就不可以被修改

4)修飾參數的時候,此參數在整個方法內部不允許被修改,修飾實參

2)int和Integer有什么區別?

1)基本數據類型是指不可再分的原始數據類型,內存中直接存儲此類型的值,通過內存地址直接可以訪問到該數據,并且內存區域只能存放這種類型的值

2)因為Java的設計理念是一切皆對象,在很多情況下,需要以對象的形式來進行操作,比如說hashcode獲取哈希值,以及getClass獲取到類對象

3)在JAVA中每一種數據類型都對應著一個包裝類,而int對應的包裝類就是Integer,包裝類的解決了基本數據類型無法做到的,實現泛型類型參數

1)數據類型不同:int是基本數據類型,Integer是包裝類類型

2)默認值不同:int 的默認值是0,Integer的默認值是null

3)內存中存儲的方式不同,int在內存中存儲的是數據值,而Integer實際上存儲的是對象引用,當我們new Integer()實際上是生成一個指針指向該對象

4)實例化方式不同:Integer必須要new

5)比較方式不同,int可以使用==來比較兩個兩個變量是否相等,而Integer一定要使用equals來進行比較啷個變量是否相等

3)finally語句塊一定會被執行嗎?當然不一定

finally更多用于try finally和try catch finally來進行關閉類似于JDBC連接和保證釋放鎖等動作

1)try語句沒有執行到,如果在try語句執行之前就return返回了,這樣finally語句塊就不會執行

2)當一個線程再進行執行try語句塊的時候或者catch語句塊的時候被打斷(interrupted)或者被終止(killed),那么與其相應的finally代碼可能不會被執行

3)當我們的try語句塊或者catch語句塊里面有System.exit(0)這樣的語句塊,他主要是終止JAVA虛擬機的,連JVM都停止了,所有都結束了

4)finally代碼塊實在守護線程里面,所有線程都執行完成了,那么守護線程就會立即停止,退出JAVA虛擬機

此外我們還需要注意一下在我們的try-catch-finally語句塊里面

1)try catch 語句塊里面有return,finally也會被執行

2)finlly語句塊里面有return語句會把try catch語句塊里面的return 語句效果給覆蓋掉

Throw和Throws的區別:

1)位置不同:

throws 用在方法上,后面跟的是異常類,可以跟多個,提醒調用者去捕獲異常

而 throw 用在方法內,后面跟的是異常對象

2)功能不同:
throws 用來聲明異常,讓調用者只知道該功能可能出現的問題,可以給出預先的處理方式,
throw 拋出具體的問題對象(指拋出的一個具體的異常類型),執行到 throw,功能就已經結束了,也就是說 throw 語句獨立存在時,下面不要定義其他語句,因為執行不到;

3)兩者都是消極處理異常的方式,只是拋出或者可能拋出異常,但是不會由方法去處理異常,真正的處理異常由方法的上層調用處理,throw一般是拋出自定義異常


finalize方法使用

1)當我們的對象回收的時候,系統會默認調用該對象的finalize方法,子類可以重寫該方法,做一些釋放資源的操作,但是finalize是Object類的方法,在JAVA中由于垃圾回收器的機制時自動回收,所以回收的時機具有不確定性,所以這個方法可能自始至終都不會被調用

2)那么什么情況下對象會被回收呢?是當某個對象沒有任何引用來指向這個對象的時候,JVM就認為這個對象是一個垃圾對象,當使用垃圾回收機制銷毀該對象的時候,會先調用finalize方法

3)垃圾回收機制的調用,是由系統來進行決定的,也是可以通過System.Gc()來觸發垃圾回收機制

public class HelloWorld {static class Student{public String username;public int age;public Student(String username, int age) {this.username = username;this.age = age;}@Overrideprotected void finalize() throws Throwable {System.out.println("這個對象要被回收了");}}public static void main(String[] args) {Student student=new Student("李佳偉",19);student=null; //這個時候new Student()對象就是一個垃圾,垃圾回收期就會進行回收,在進行銷毀對象之前會進行調用finalize //方法,程序員就可以在finalize來寫一些自己的業務邏輯代碼,比如說釋放資源,數據庫連接,文件關閉操作 //如果程序員不重寫這個方法,默認就會調用Object類的finalize,進行默認處理System.gc();} }

1)重寫Object類的finalize()方法,在對象被銷毀前將執行這個方法,將“對象即將被銷毀”打印到控制臺。在默認情況下,通過System.gc()或Runtime.getRuntime()的調用,會顯示的觸發FullGC,同時對老年代和新生代進行回收,會嘗試釋放掉被丟棄對象占用的內存。但是也不一定成功,只能說增大了對象被會回收的概率。

2)垃圾回收具有不確定性,也大有可能在資源耗盡前無法執行這個函數,因而最好手動調用的顯示的close()方法。

總結:

1)finalize是Object中的類的一個基礎方法,他的設定是保證對象在垃圾回收之前完成特定資源的回收,但是在JDK9之前已經被默認為棄用的方法

2)但是在實際開發中并不推薦使用finalize方法,他雖然被創造出來但是無法保證這個方法一定會被執行,所以不要依賴它釋放任何資源,因為他的運行極其的不穩定

3)finalize除了執行不穩定之外,還有一定的性能問題,因為finalize的設計是和垃圾收集關聯到一起的,一旦出現了非空的finalize方法,就會導致對象回收呈現數量級上面的變慢,有人做過benchmark,大概是40-50倍的下降

4)所以說finalize被設計成在對象被垃圾回收之前調用,這就意味著實現finalize的方法的對象是一個特殊公民,JVM要額外對它進行處理,finalize本質上成為了快速回收垃圾的阻礙者,可能會導致你的對象經過多個垃圾回收周期才可以被使用

總結

以上是生活随笔為你收集整理的异常--------JavaSE的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。