異常就是java中出現的不正常的現象(錯誤與異常),按照繼承的體系結構,能夠分類以下
html
Throwable: 它是全部錯誤與異常的超類(祖宗類)java
|- Error 錯誤,修改java源代碼數據庫
|- Exception 編譯期異常, javac.exe進行編譯的時候報錯編程
|- RuntimeException 運行期異常, java出現運行過程當中出現的問題api
1.出現問題,本身解決數組
try{bash
可能出現異常的代碼網絡
} catch(異常類名 對象名){jvm
異常處理代碼socket
} finally {
異常操做中必定要執行的代碼
}
2.出現問題,別人解決
格式:
修飾符 返回值類型 方法名(參數) throws 異常類名1,異常類名2,...{}
public void method() throws ATMException{}
異常:程序在運行期間發生了異常,一般能夠有針對性的處理方式的。
錯誤:程序在運行期間發生了錯誤,一般不會有針對性的處理方式。錯誤的的發生每每都是系統級別的問題,都是jvm所在系統發生的並反饋給jvm的。沒法針對處理,只能修正代碼。
異常代碼體現:
class ExceptionDemo {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[3]);// 該句運行時發生了ArrayIndexOutOfBoundsException,致使程序沒法繼續執行。程序結束。
System.out.println("over"); // 因爲上面代碼發生了異常,此句代碼不會執行
}
}
複製代碼
錯誤的體現:
int[] arr = new int[1024*1024*100];//OutOfMemoryError 開闢了過大的數組空間,致使JVM在分配數組空間時超出了JVM內存空間,直接發生錯誤。
複製代碼
class ArrayTools{
/*
對給定的數組經過給定的角標獲取元素。
*/
int getElement(int[] arr,int index) {
/*
沒有找到4個角標。運行時發生了問題,這個問題JVM認識。這個問題java自己有
描述:描述內容有:問題的名稱,問題的內容,問題的發生位置。既然有這麼多的信
息。java就將這些信息直接封裝到對象中。ArrayIndexOutOfBoundsException
*/
int element = arr[index];//throw new ArrayIndexOutOfBoundsException(index);
return element;
}
}
複製代碼
class ExceptionDemo2 {
public static void main(String[] args) {
ArrayToolsd = new ArrayTools();
int[] arr = {34,12,67};
int num = d.getElement(arr,4);//收到 new ArrayIndexOutOfBoundsException(index);拋出jvm。jvm進行最終處理。將問題的名稱,信息,位置都顯示屏幕上。
System.out.println("num="+num);
System.out.println("over");
}
}
複製代碼
在編寫程序時,必需要考慮程序的問題狀況。好比在寫功能時,須要接受參數,在使用功能中使用接受到的參數時,首先須要先對參數數據進行合法的判斷,數據若不合法,應該告訴調用者,傳遞合法的數據進來。這時須要使用異常這種方法來告訴調用者。因此定義程序須要考慮程序的健壯性
。
class ArrayTools{
/*
對給定的數組經過給定的角標獲取元素。
*/
int getElement(int[] arr,int index) {
/*
jvm出了問題,本身打包對象並拋出。可是它所提供的信息不夠給力。想要更清晰,
須要本身寫。它的拋出不知足咱們的要求。準備本身拋。
*/
if(arr==null) {
throw new NullPointerException("arr指向的數組不存在");
}
if(index<0 || index>=arr.length){
//該條件若是知足,功能已經沒法繼續運算。這時就必須結束功能,並將問題告知給調用者。這時就須要經過異常來解決。
//怎麼使用異常呢?
//1,建立一個異常對象。封裝一些提示信息(自定義)。
//2,須要將這個對象告知給調用者。怎麼告知呢?怎麼將這個對象傳遞到調用者處呢?經過關鍵字throw就能夠完成。 throw 異常對象;
//3,throw用在函數內,拋出異常對象,並能夠結束函數。
throw new ArrayIndexOutOfBoundsException("錯誤的角標,"+index+"索引在數組中不存在");
}
int element = arr[index];
return element;
}
}
複製代碼
class ExceptionDemo3 {
public static void main(String[] args) {
Demo d = new Demo();
int[] arr = {34,12,67};
int num = d.getElement(null,2);
System.out.println("num="+num);
System.out.println("over");
}
}
複製代碼
在查閱API時,發現異常有分類,而且有些編輯報錯,有些編譯不報錯,那究竟是爲何呢?
在上述自定義異常中繼承Exception和繼承RuntimeExcpetion爲何差距這麼大?
一、Exception異常(非RuntimeException)
在函數內拋出Exception,編譯失敗,由於編譯器在檢查語法時發生了錯誤。該程序已經出現問題,Java認爲這個程序自己存在隱患,須要捕獲或者聲明出來(你要麼把問題處理,要麼把問題標識出來讓調用知道)。
二、RuntimeException異常
爲何拋出RuntimeException,不須要捕獲,不要聲明呢?不是功能自己發生的異常,而是由於好比調用者傳遞參數錯誤而致使功能運行失敗。這也是問題,須要經過異常來體現,可是這個異常不要聲明出來的。聲明的目的是爲了讓調用者進行處理。不聲明的目的是不讓調用者進行處理,就是爲了讓程序中止,讓調用者看到現象,並進行代碼的修正。
三、異常分兩種:
a、編譯時異常:編譯器會檢測的異常。
b、運行時異常:編譯器不會檢測的異常。不須要聲明。聲明也能夠,若是聲明瞭,無外 乎就是讓調用者給出處理方式。
在研究異常分類時,發現有關於異常的聲明和捕獲,到底啥是異常聲明,啥是異常捕獲呢?
聲明:將問題標識出來,報告給調用者。若是方法內經過throw拋出了編譯時異常,而沒有捕獲,那麼必須經過throws進行聲明,讓調用者去處理。
捕獲:Java中對異常有針對性的語句進行捕獲。
捕獲格式:
try
{
//須要被檢測的語句。
}
catch(異常類 變量)//參數。
{
//異常的處理語句。
}
finally
{
//必定會被執行的語句。
}
複製代碼
class Demo{
/*
若是定義功能時有問題發生須要報告給調用者。能夠經過在函數上使用throws關鍵字進行聲明。
*/
void show(int x)throws Exception {
if(x>0){
throw new Exception();
} else {
System.out.println("show run");
}
}
}
複製代碼
class ExceptionDemo{
public static void main(String[] args) {//throws Exception//在調用者上繼續聲明。
Demo d = new Demo();
try {
d.show(1);//當調用了聲明異常的方法時,必須有處理方式。要麼捕獲,要麼聲明。
}
catch (Exception ex) { //括號中須要定義什麼呢?對方拋出的是什麼問題,在括號中就定義什麼問題的引用。
System.out.println("異常發生了");
}
System.out.println("Hello World!");
}
}
複製代碼
聲明和捕獲的應用
class NoAgeException extends RuntimeException{
NoAgeException() {
super();
}
NoAgeException(String message) {
super(message);
}
}
複製代碼
class Person{
private String name;
private int age;
Person(String name,int age)//throws NoAgeException {
//加入邏輯判斷。
if(age<0 || age>200) {
throw new NoAgeException(age+",年齡數值非法");
}
this.name = name;
this.age = age;
}
//定義Person對象對應的字符串表現形式。覆蓋Object中的toString方法。
public String toString() {
return "Person[name="+name+",age="+age+"]";
}
}
複製代碼
class ExceptionDemo{
public static void main(String[] args) {
try {
Person p = new Person("xiaoming",20);
System.out.println(p);
}
catch (NoAgeException ex){
System.out.println("異常啦");
}
System.out.println("over");
}
}
複製代碼
構造函數到底拋出這個NoAgeException是繼承Exception呢?仍是繼承RuntimeException呢?
繼承Exception,必需要throws聲明,一聲明就告知調用者進行捕獲,一旦問題處理了調用者的程序會繼續執行。
繼承RuntimeExcpetion,不須要throws聲明的,這時調用是不可能編寫捕獲代碼的,由於調用根本就不知道有問題。一旦發生NoAgeException,調用者程序會停掉,並有jvm將信息顯示到屏幕,讓調用者看到問題,修正代碼。
在上述代碼中,發現這些異常都是JDK內部定義好的,而且這些異常很差找。書寫時也很不方便,那麼能不能本身定義異常呢?
以前的幾個異常都是java經過類進行的描述。並將問題封裝成對象,異常就是將問題封裝成了對象。這些異常很差認,書寫也很不方便,能不能定義一個符合個人程序要求的問題名稱。既然JDK中是使用類在描述異常信息,那麼咱們也能夠模擬Java的這種機制,咱們本身定義異常的信息,異常的名字,讓異常更符合本身程序的閱讀。準確對本身所須要的問題進行類的描述。
class NoAgeException
{
/*
爲何要定義構造函數,看到Java中的異常描述類中有提供對問題對象的初始化方法。
*/
NoAgeException()
{
}
NoAgeException(String message)
{
}
}
class Person{
private String name;
private int age;
Person(String name,int age) {
//加入邏輯判斷。
if(age<0 || age>200){
throw new NoAgeException(age+",年齡數值非法");
}
this.name = name;
this.age = age;
}
//定義Person對象對應的字符串表現形式。覆蓋Object中的toString方法。
public String toString(){
return "Person[name="+name+",age="+age+"]";
}
}
class ExceptionDemo{
public static void main(String[] args) {
Person p = new Person("xiaoming",-20);
System.out.println(p);
}
}
複製代碼
上述代碼發生編譯失敗。
ExceptionDemo.java:19: 錯誤: 不兼容的類型
throw new NoAgeException(age+",年齡數值非法");
^
須要: Throwable
找到: NoAgeException
1 個錯誤
複製代碼
提示中說須要Throwable,啥東西?搜索API。看到Throwable描述。發現。它是異常和錯誤的超類(父類),原來它是異常體系的頂層類。
經過閱讀:自定義異常被拋出,必須是繼承Throwable,或者繼承Throwable的子類。該對象才能夠被throw拋出。原來這個異常體系具有一個特有的特性:可拋性:能夠被throw關鍵字操做
。
異常繼承選擇父類時,更爲確切是繼承Exception。可是發現編譯又一次失敗了。
class NoAgeException extends Exception{
/*
爲何要定義構造函數,由於看到Java中的異常描述類中有提供對問題對象的初始化方法。
*/
NoAgeException() {
}
NoAgeException(String message) {
}
}
ExceptionDemo.java:19: 錯誤: 未報告的異常錯誤NoAgeException; 必須對其進行捕獲或聲明以便拋出
throw new NoAgeException(age+",年齡數值非法");
^
1 個錯誤
複製代碼
經過這個編譯失敗提示,發現自定義的異常和以前所使用的異常(空指針異常,角標越界異常,無效參數異常有不一樣),拋出哪些異常沒有這個失敗提示?那麼以前的異常和自定義的異常有什麼區別呢?
經過查看api的繼承體系發現,以前的異常都是Exception下面的RuntimeException子類的子類。閱讀RuntimeException描述中有明確說明,這個運行時異常以及其子類都無需進行聲明。
能夠將自定義的異常繼承RuntimeException.
class NoAgeException extends RuntimeException
{
/*
爲何要定義構造函數,由於看到Java中的異常描述類中有提供對問題對象的初始化方法。
*/
NoAgeException() {
}
NoAgeException(String message) {
}
}
複製代碼
發現編譯運行的確正常運行,可是異常提示信息沒有了,爲何呢,查閱異常源碼,發現本身父類構造函數中有關於異常信息的操做,那麼在本身定義的異常中須要將這些信息傳遞給父類,讓父類幫咱們進行封裝便可。
class NoAgeException extends RuntimeException{
/*
爲何要定義構造函數,由於看到Java中的異常描述類中有提供對問題對象的初始化方法。
*/
NoAgeException() {
super();
}
NoAgeException(String message) {
super(message);// 若是自定義異常須要異常信息,能夠經過調用父類的帶有字符串參數的構造函數便可。
}
}
複製代碼
一、throw用在函數內。throws用在函數上。
二、thorw拋出的是異常對象。throws用於進行異常類的聲明,後面異常類能夠有多個,用逗號隔開。
有一些特定的代碼不管異常是否發生,都須要執行。由於異常會引起程序跳轉,致使有些語句執行不到。沒法知足這個需求。異常捕獲處理時java提供解決方案,finally就是解決這個問題的,這個代碼塊中存放的代碼都是必定會被執行的。
//自定義異常
class NoShowException extends Exception
{
NoShowException(String message)
{
super(message);
}
}
//模擬功能類
class Demo
{
void show(int num) throws NoShowException
{
if(num < 5)
{
throw new NoShowException(num+"非法的數據");
}
System.out.println("show num"+num);
}
}
//測試類
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
d.show(4);
}
catch (NoShowException ex)
{
System.out.println(ex); //打印異常信息
//若是異常發生,處理完畢後,但願功能結束;
//可使用return ;
}
finally
{
System.out.println("一直能執行到的代碼");
}
System.out.println("Hello World!");
}
}
複製代碼
總結:finally到底何時用?
只要程序中使用到了具體的資源(數據庫鏈接,IO資源,網絡鏈接socket等)須要釋放,都必須定義在finally中。你在定義程序,只要問題發生與否,指定程序都須要執行時,就定義finally中。
try catch組合 : 對代碼進行異常檢測,並對檢測的異常傳遞給catch處理。異常捕獲處理。
void show(){ //不用throws
try{
throw new Exception();
}catch(Exception e){
//處理方式
}
}
複製代碼
try finally 組合: 對代碼進行異常檢測,檢測到異常後由於沒有catch,因此同樣會被默認jvm拋出。異常是沒有捕獲處理的。可是功能所開啓資源須要進行關閉,全部finally。只爲關閉資源。
void show(){//須要throws
try{
throw new Exception();
}finally {
//關閉資源
}
}
複製代碼
try catch finally組合:檢測異常,並傳遞給catch處理,並定義資源釋放。
異常在繼承或者實現中的使用細節:
一、子類覆蓋父類方法時,若是父類的方法聲明異常,子類只能聲明父類異常或者該異常的子類,或者不聲明。
二、當父類方法聲明多個異常時,子類覆蓋時只能聲明多個異常的子集。
三、當被覆蓋的方法沒有異常聲明時,子類覆蓋時沒法聲明異常的。
舉例:父類中會存在下列這種狀況,接口也有這種狀況,
問題:接口中沒有聲明異常,而實現的子類覆蓋方法時發生了異常,怎麼辦?
答:沒法進行throws聲明,只能catch的捕獲。萬一問題處理不了呢?catch中繼續throw拋出,可是隻能將異常轉換成RuntimeException子類拋出。
java編程思想
黑馬視頻