1. 程式人生 > 實用技巧 >贊!7000 字學習筆記,一天搞定 MySQL

贊!7000 字學習筆記,一天搞定 MySQL

1 java的異常處理機制
1.1 異常在java中以類和物件的形式存在。那麼異常的繼承結構是怎麼樣的?
我們可以使用UML圖來描述一下結構繼承。
畫UML圖有很多工具,例如:Rational Rose(收費的)、startUML等...
Object
Object下有Throwable(可丟擲的)
Throwable下有兩個分支:Error(不可處理的,直接退出JVM)和Exception(可處理的)
Exception下有兩個分支:
Exception的直接子類:編譯時異常。(要求程式設計師在編寫程式階段必須預先對這些異常進行處理,如果不處理編譯器報錯,因此得名編譯時異常。)
RuntimeException:執行時異常。(在編寫程式階段程式設計師可以預先處理,也可以不管,都行。)


1.2 編譯時異常和執行是異常,都是發生在執行階段。編譯階段異常是不會發生的。
編譯時異常因為什麼而得名?
因為編譯時異常必須在編譯(編寫)階段預先處理,如果不處理編譯器報錯,因此得名。
所有一摻個都是在執行階段發生的,因為只有程式執行階段才可以new物件。
因為異常的發生就是new異常物件。

1.3 編譯時異常和執行時異常的區別?
編譯時異常一般發生的概率比較高。
執行時異常一般發生的概率比較低。
舉個例子:
你看到外面下雨了,傾盆大雨的。
你出門之前會預料到:如果不打傘,我可能會生病(生病是一種異常)。
而且這個異常發生的概率很高,所以我們出門之前要拿一把傘。
“拿一把傘”就是對“生病異常”發生之前的一種處理方式。

對於一些發生概率較高的異常,需要在執行之前對其進行預處理。

執行時異常一般發生的概率比較低。
舉個例子:
小明走在大街上,可能會被天上的飛機輪子砸到。
被飛機輪子砸到也算一種異常。
但是這種異常發生概率較低。
再出門之前你沒必要提前對這種發生概率較低的異常進行預處理。
如果你預處理這種異常,你將活的很累。

假設你再出門之前,你把能夠發生的異常都預先處理,你這個人會更加的安全,但是你這個人活的很累。

假設java中沒有對異常進行劃分,沒有分為:編譯時異常和執行時異常。
所有的異常都需要在編寫階段對其進行預處理,將是怎樣的效果呢?
首先,如果這樣的話,程式肯定是絕對安全的。
但是程式設計師編寫程式太累,程式碼到處都是處理異常的程式碼。

1.4 編譯時異常還有其他名字:
受檢異常:CheckdException
受控異常

1.5 執行時異常還有其他名字:
未受控異常:UnCheckdException
非受控異常。

1.6 再次強調:所有的異常都是發生在執行階段的。

1.7 java語言中對異常的處理包括兩種方式:
第一種方式:在方法生命的位置上,使用throws關鍵字,拋給上一級。
誰呼叫我,我就拋給誰。拋給上一級。

第二種方式:使用try..catch語句進行異常的捕捉。
這件事發生了,誰也不知道,因為我給抓住了。

舉個例子:
我是某集團的一個銷售員,因為我得失誤,導致公司損失了1000元,
“損失1000元”這可以看做是一個異常發生了。我有兩種處理方式,
第一種方式:我把這件事情告訴我的領導【異常上拋】
第二種方式:我自己掏腰包把這個錢補上。【異常的捕捉】

什麼是異常,java提供異常機制有什麼用?

package com.javase.Exception;
/*
1 什麼是異常,java提供異常機制有什麼用?
    以下程式執行過程中發生了不正常的情況,而這種不正常的情況叫做:異常
    java語言是很完善的語言,提供了異常的處理方式,以下程式執行過程中出現了不正常情況,
    java把該異常資訊列印輸出到控制檯,供程式設計師參考。
    程式設計師看到以後,可以對程式進行修改,讓程式更加的健壯。
    
    什麼是異常:程式執行過程中的不正常情況。
    異常的作用:增強程式的健壯性。
    
2 以下程式執行控制檯出現了:
    Exception in thread "main" java.lang.ArithmeticException: / by zero
   at com.javae.Exception.ExceptionTest01.main(ExceptionTest01.java:17)
   這個資訊被我們稱作:異常資訊。這個資訊是JVM列印的。
*/
public class ExceptionTest01 {
    public static void main(String[] args) {
        
        int a= 10;
        int b = 1;
        // 實際上JVM在執行到此處的時候,會new異常物件。 new ArithmeticException("/ by zero");物件
        // 並且JVM將new的異常物件丟擲,列印輸出資訊到控制檯了。
        int c = a / b;
        System.out.println(a +" / "+ b + " = " + c);
        
        // 此處執行也會建立一個:ArithmeticException型別的物件。
        System.out.println(100 / 0);
        
        // 我觀察到異常資訊之後,對程式進行修改,更加健壯。
        /*int a = 10;
        int b = 0;
        if(b == 0){
            System.out.println("除數不能為0");
            return;
        }
        // 程式執行到此處表示除數一定不是0
        int c = a / b;
        System.out.println(a +" / "+ b + " = " + c);*/
    }
}

java語言中異常是以什麼形式存在的呢?
package com.javase.Exception;
/*
java語言中異常是以什麼形式存在的呢?
    1 異常在java中以類的形式存在,每一個異常都是一個類。
    2 異常對應的現實生活中是怎樣的?
        火災(異常類):
            2008年8月8日小明家著火了(異常物件)
            2008年8月18日小剛家著火了(異常物件)
            2008年8月28日小紅家著火了(異常物件)
        類是:模板。
        物件是:實際存在的個體。
        
        錢包丟了(異常類):
            2008年1月8日:小明的錢包丟了(異常物件)
            2008年1月9日:小明的錢包又丟了(異常物件)
            ...
*/
public class ExceptionTest02 {
    public static void main(String[] args) {
        // 通過"異常類"例項化"異常物件"
        NumberFormatException numberFormatException = new NumberFormatException("數字格式化異常");
        
        // java.lang.NumberFormatException: 數字格式化異常
        System.out.println(numberFormatException);
        
        // 通過“異常類”建立“異常物件”
        NullPointerException nullPointerException = new NullPointerException("空指標異常發生了");
        // java.lang.NullPointerException: 空指標異常發生了
        System.out.println(nullPointerException);
    }
}

ArithmeticException異常案例:
package com.javase.Exception;


public class ExceptionTest03 {
    public static void main(String[] args) {
        /*
        程式執行到此處發生了ArithmeticException: / by zero異常。
        底層new了一個ArithmeticException異常物件。
        然後丟擲了,由於是main方法呼叫了100/0
        所以這個異常ArithmeticException拋給了main方法
        main方法沒有處理,將這個異常拋給了JVM。
        JVM最終終止程式的執行。
        
        ArithmeticException繼承了RunTimeException,屬於執行時異常。
        在編寫程式階段不需要對這種異常進行預先的處理。
         */
        System.out.println(100 / 0);
        
        // 這裡的Hello World沒有輸出,沒有執行。
        System.out.println("Hello World");
    }
}

分析程式碼異常報錯原因案例:

package com.javase.Exception;
/*
以下程式碼報錯的原因是什麼?
    因為doSome()方法宣告位置上使用了throws ClassNotFoundException
    而ClassNotFoundException是編譯時異常。必須編寫程式碼時處理,沒有處理編譯器報錯
*/
public class ExceptionTest04 {
    public static void main(String[] args) {
        // main方法中呼叫doSome()方法
        // 因為doSome()方法宣告位置上有:throws ClassNotFoundException
        // 我們在呼叫doSome()方法的時候必須對著彙總異常進行預先的處理。
        // 如果不處理,編譯器就會報錯。
        // 編譯器報錯資訊:Unhandled exception: java.lang.ClassNotFoundException
        // doSome();
    }
    
    /**
     * doSome方法在宣告的位置使用了:throws ClassNotFoundException
     * 這個程式碼表示doSome()方法在執行過程中,有可能會出現ClassNotFoundException異常。
     * 叫做類沒有找到異常,這個異常直接父類是:Exception,所以ClassNotFoundException屬於編譯時異常。
     * @throws ClassNotFoundException
     */
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome方法執行了");
    }
}

異常的捕捉和上拋:
package com.javase.Exception;


public class ExceptionTest05 {
    // 第一種處理方式:在宣告的位置上繼續使用:throws來完成異常的繼續上拋,拋給呼叫者。
    // 上拋類似於推卸責任(繼續向上拋給呼叫者)
    /*public static void main(String[] args) throws ClassNotFoundException{
        doSome();
    }*/
    
    // 第二種處理方式:try..catch進行捕捉
    // 不做等於把異常攔下了,異常真正的解決了。(呼叫者是不知道的。)
    public static void main(String[] args) {
        try {
            doSome();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome方法執行了");
    }
}

異常的上報和捕捉:

package com.javase.Exception;


import java.io.FileNotFoundException;
import java.io.FileOutputStream;


/*
處理異常的第一種方式:在方法宣告的位置使用throws關鍵字丟擲,誰呼叫我這個方法,我就拋給誰,拋給呼叫者處理。
    這種處理異常的態度:上報。
    
處理異常的第二種方式:
    使用try..catch語句對異常進行捕捉。
    這個異常不會上報,自己把這個事處理了。
    異常拋到此處為止,不在上拋了。
    
注意:
    只要異常沒有捕捉,採用上報的方式,此方法的後續程式碼不會執行。
    另外需要注意,try語句塊中的某一行出現異常,該行後面的程式碼不會執行。
    try..catch執行完成後,該方法後面的java語句會執行。
*/
public class ExceptionTest06 {
    // 一般不建議在main方法上使用throws,因為這個異常如果真正發生了,一定會拋給JVM、JVM只有終止。
    // 異常處理機制的作用就是增強程式的健壯性,怎麼能做到、異常發生了也不影響程式的執行。
    // 所以一般main方法中的異常建議使用try..catch進行捕捉,main就不要繼續向上拋了。
    public static void main(String[] args) {
        System.out.println("main begin");
        // try嘗試
        try {
            m1();
        // 以上程式碼出現異常,直接進入catch語句塊中執行。
        } catch (FileNotFoundException e) { // catch後面的好像一個方法的形參
            // 這個分支中可以使用e引用,e引用儲存的記憶體地址是那個new出來異常物件的記憶體地址。
            // catch是捕捉 異常之後走的分支
            // 在catch分支中幹什麼?處理異常。
            System.out.println("檔案不存在,可能路徑錯誤!也可能該檔案被刪除了。");
            System.out.println(e);// java.io.FileNotFoundException: C:哇哈哈哈哈哈哈哈哈.txt (拒絕訪問。)
        }
        // try..catch把異常抓住以後,這裡的程式碼會繼續執行。
        System.out.println("main end");
        
    }
    
    public static void m1() throws FileNotFoundException {
        System.out.println("m1 begin");
        m2();
        // 出現異常以下程式碼不會被執行
        System.out.println("m1 end");
    }
    
    // 拋別的不行,拋ClassCastException說明你還是沒有對FileNOtFoundException進行處理
    // 拋FileNotFoundException的父類物件IOException,這樣是可以的。因為IOException包括FileNotFoundException
    // private static void m2() throws FileNotFoundException {
    // 這樣也可以,因為Exception包括所有的異常。
    // private static void m2() throws Exception {
    // throws後面也可以寫多個異常,使用逗號隔開
    // private static void m2() throws ClassNotFoundException,FileNotFoundException{
    private static void m2() throws FileNotFoundException{
        System.out.println("m2 begin");
        m3();
        // 出現異常以下程式碼不會被執行
        System.out.println("m2 end");
    }
    
    private static void m3() throws FileNotFoundException {
        // 呼叫SUN jdk中某個類的構造方法
        // 這個類還沒有接觸過,後期IO流的時候就知道了。
        // 我們只是藉助這個類學習一下異常處理機制。
        // 建立一個輸入流物件,該流指向一個檔案。
        System.out.println("m3 begin");
        /*
        編譯報錯的原因是什麼?
            1 第一:這裡呼叫了一個構造方法:FileInputStream(String name)
            2 第二:這個構造方法的宣告位置上有:throws FileNotFoundException
            3 第三:通過類的繼承結構看到:FileNotFoundException的父類是IOException,IOException的父類是Exception
            最終得知,FileNotFoundException是編譯時異常。
            
            錯誤原因?編譯時異常要求程式設計師編寫程式階段必須對他進行處理,不處理編譯器報錯。
            
         */
        // 我們採用第一種處理方式:在方法宣告的位置上使用throws繼續上拋。
        // new FileOutputStream("C:\\Users\\xlWu\\Desktop\\學習\\異常\\學習.txt");
        new FileOutputStream("C:哇哈哈哈哈哈哈哈哈.txt");
        // 出現異常以下程式碼不會被執行
        System.out.println("m1 end");
    }
}

深入try..catch:
package com.javase.Exception;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;


/*
深入try..catch
    1 catch後面的小括號中的型別可以是具體的異常型別,也可以是該異常型別的父型別。
    2 catch可以寫多個,建議catch的時候,精確的一個一個處理,這樣有利於程式的除錯。
    3 catch寫多個的時候,從上到下,必須遵循從小到大。
    
在以後的開發中,處理編譯時異常,應該上報還是捕捉呢,怎麼選?
    如果希望呼叫者來處理,選擇throws上報。
    其它情況使用捕捉的方式。
*/
public class ExceptionTest07 {
    /*public static void main(String[] args) throws Exception, FileNotFoundException,NullPointerException,NumberFormatException {
    
    }*/
    
    /*public static void main(String[] args) throws Exception {
    
    }*/
    
    public static void main(String[] args) {
        /*try {
            FileInputStream fis =  new FileInputStream("D:\\Users\\xlWu\\Desktop\\學習\\異常\\異常的繼承結構圖.uml");
            System.out.println("出現異常,這裡無法執行!");
        } catch (FileNotFoundException e) {
            System.out.println("檔案不存在!");
        }
    
        System.out.println("hello world!");*/
    
        /*try {
            FileInputStream fis =  new FileInputStream("D:\\Users\\xlWu\\Desktop\\學習\\異常\\異常的繼承結構圖.uml");
            System.out.println("出現異常,這裡無法執行!");
        *//*} catch (IOException e) {// 多型 IOException e = new FileNotFoundException();*//*
        } catch (Exception e) {// 多型 Exception e = new FileNotFoundException();
            System.out.println("檔案不存在!");
        }*/
    
        /*try {
            // 建立輸入流
            FileInputStream fis =  new FileInputStream("D:\\Users\\xlWu\\Desktop\\學習\\異常\\異常的繼承結構圖.uml");
            // 讀檔案
            fis.read();
        } catch (Exception e) { // 所有的異常都走這個分支
            System.out.println("檔案不存在!");
        }*/
    
        /*try {
            // 建立輸入流
            FileInputStream fis =  new FileInputStream("D:\\Users\\xlWu\\Desktop\\學習\\異常\\異常的繼承結構圖.uml");
            // 讀檔案
            fis.read();
        } catch (FileNotFoundException e) {
            System.out.println("檔案不存在!");
        } catch (IOException e) {
            System.out.println("讀檔案報錯了!");
        }*/
        
        // 編譯報錯  自上而下執行  必須由小到大
        /*try {
            // 建立輸入流
            FileInputStream fis =  new FileInputStream("D:\\Users\\xlWu\\Desktop\\學習\\異常\\異常的繼承結構圖.uml");
            // 讀檔案
            fis.read();
        } catch (IOException e) {
            System.out.println("檔案不存在!");
        } catch (FileNotFoundException e) {
            System.out.println("讀檔案報錯了!");
        }*/
        
        // JDK8的新特性
        try {
            // 建立輸入流
            FileInputStream fis =  new FileInputStream("D:\\Users\\xlWu\\Desktop\\學習\\異常\\異常的繼承結構圖.uml");
            // 進行數學運算
            System.out.println(10 / 0);// 這個是執行時異常,編寫程式時可以處理,也可以不處理。
        } catch (FileNotFoundException | ArithmeticException | NullPointerException e) {
            System.out.println("檔案不存在?數學異常?空指標異常?都有可能!");
        }
    }
}