1. 程式人生 > >day19(異常&IO(File類))

day19(異常&IO(File類))

###19.01_異常(異常的概述和分類)

 A:異常的概述

     異常就是Java程式在執行過程中出現的錯誤。

 B:異常的分類

     通過API檢視Throwable

     Error

         伺服器宕機,資料庫崩潰等

     Exception

C:異常的繼承體系

     Throwable

         Error    

         Exception

             RuntimeException

int[] arr = {11,22,33,44,55};

    //arr = null; //NullPointerException 空指標異常

    System.out.println(arr[10]); //ArrayIndexOutOfBoundsException陣列索引越界異常

 

###19.02_異常(JVM預設是如何處理異常的)

 A:JVM預設是如何處理異常的

     main函式收到這個問題時,有兩種處理方式:

      a:自己將該問題處理,然後繼續執行

      b:自己沒有針對的處理方式,只有交給呼叫main的jvm來處理

      jvm有一個預設的異常處理機制,就將該異常進行處理.

      並將該異常的名稱,異常的資訊.異常出現的位置列印在了控制檯上,同時將程式停止執行

 B:案例演示

     JVM預設如何處理異常

 

 

###19.03_異常(try...catch的方式處理異常1)

 A:異常處理的兩種方式

     a:try…catch…finally

         try catch

         try catch finally

         try finally

     b:throws

 B:try...catch處理異常的基本格式

     try…catch…finally

 C:案例演示

     try...catch的方式處理1個異常

try:用來檢測異常的

catch:用來捕獲異常的

finally:釋放資源

 

//世界上最真情的相依就是你在try我在catch,無論你發神馬脾氣,我都靜靜接受,默默處理

//當通過trycatch將問題處理了,程式會繼續執行

    try{ //try:用來檢測異常的

int x = d.div(10, 0);

System.out.println(x);

    }catch(ArithmeticException a) { //ArithmeticException a = new ArithmeticException();

System.out.println("出錯了,除數為零了");

    }

    //當通過trycatch將問題處理了,程式會繼續執行

    System.out.println("1111111111111111");

 

###19.04_異常(try...catch的方式處理異常2)

 A:案例演示

     try...catch的方式處理多個異常

     JDK7以後處理多個異常的方式及注意事項

    * 安卓,客戶端開發,如何處理異常?try{}catch(Exception e){}

    * ee,服務端開發,一般都是底層開發,從底層向上拋

    *

    * try後面如果跟多個catch,那麼小的異常放前面,大的異常放後面,根據多型的原理,如果大的放前面,就會將所有的子類物件接收

    * 後面的catch就沒有意義了

   int a = 10;

   int b = 0;

   int[] arr = {11,22,33,44,55};

 

   try {

System.out.println(a / b);

System.out.println(arr[10]);

arr = null;

System.out.println(arr[0]);

   } catch (ArithmeticException e) {

System.out.println("除數不能為零");

   } catch (ArrayIndexOutOfBoundsException e) {

System.out.println("索引越界了");

   } catch (Exception e) { //Exception e = new NullPointerException();

System.out.println("出錯了");

    }

 

    System.out.println("異常處理後繼續向下執行");

 

    //JDK7如何處理多個異常

    try {

System.out.println(a / b);

System.out.println(arr[10]);

    } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {

System.out.println("出錯了");

    }

 

###19.05_異常(編譯期異常和執行期異常的區別)

 A:編譯期異常和執行期異常的區別

     Java中的異常被分為兩大類:編譯時異常和執行時異常。

     所有的RuntimeException類及其子類的例項被稱為執行時異常,其他的異常就是編譯時異常

    

     編譯時異常

         Java程式必須顯示處理,否則程式就會發生錯誤,無法通過編譯

     執行時異常

         無需顯示處理,也可以和編譯時異常一樣處理

 B:案例演示

     編譯期異常和執行期異常的區別

編譯時異常也叫做未雨綢繆異常(老師自己定義的)

未雨綢繆:在做某些事情的時候要做某些準備

編譯時異常:在編譯某個程式的時候,有可能會有這樣那樣的事情發生,比如檔案找不到,這樣的異常就必須在編譯的時候處理

如果不處理編譯通不過

 

執行時異常:就是程式設計師所犯得錯誤,需要回來修改程式碼

    try {

FileInputStream fis = new FileInputStream("xxx.txt");

    } catch(Exception e) {

    }

 

###19.06_異常(Throwable的幾個常見方法)

 A:Throwable的幾個常見方法

     a:getMessage()

         獲取異常資訊,返回字串。

     b:toString()

         獲取異常類名和異常資訊,返回字串。

     c:printStackTrace()

         獲取異常類名和異常資訊,以及異常出現在程式中的位置。返回值void。

 B:案例演示

     Throwable的幾個常見方法的基本使用

    try {

System.out.println(1/0);

    } catch (Exception e) {  //Exception e = new ArithmeticException("/ by zero");

System.out.println(e.getMessage()); /// by zero //獲取異常資訊

System.out.println(e); //java.lang.ArithmeticException: / by zero //呼叫toString方法,列印異常類名和異常資訊

e.printStackTrace(); //java.lang.ArithmeticException: / by zero

//at com.heima.exception.Demo5_Throwable.main(Demo5_Throwable.java:18)     //jvm預設就用這種方式處理異常

    }

 

###19.07_異常(throws的方式處理異常)

 A:throws的方式處理異常

     定義功能方法時,需要把出現的問題暴露出來讓呼叫者去處理。

     那麼就通過throws在方法上標識。

 B:案例演示

     舉例分別演示編譯時異常和執行時異常的丟擲

* 編譯時異常的丟擲必須對其進行處理

 

 * 執行時異常的丟擲可以處理也可以不處理

public class Demo6_Exception {

    public static void main(String[] args) {

Person p = new Person();

p.setAge(-17);

System.out.println(p.getAge());

    }

}

class Person {

    private String name;

    private int age;

    public Person() {

super();

    }

  public Person(String name, int age) {

super();

this.name = name;

this.age = age;

    }

    public String getName() {

return name;

    }

    public void setName(String name) {

this.name = name;

    }

    public int getAge() {

return age;

    }

public void setAge(int age){

if(age >0 && age <= 150) {

     this.age = age;

  }else {

     //Exception e = new Exception("年齡非法");

     //throw e;

    throw new RuntimeException("年齡非法");//在方法中丟擲執行時異常在編譯時不用對他進行處理,在方法上不丟擲也是可以的

    //如果丟擲的是編譯時異常,那麼在方法上就必須做宣告否則報錯

         }

    }

}

 

###19.08_異常(throw的概述以及和throws的區別)

 A:throw的概述

     在功能方法內部出現某種情況,程式不能繼續執行,需要進行跳轉時,就用throw把異常物件丟擲。

 B:案例演示    

     分別演示編譯時異常物件和執行時異常物件的丟擲

 C:throws和throw的區別

     a:throws

         用在方法聲明後面,跟的是異常類名

         可以跟多個異常類名,用逗號隔開

         表示丟擲異常,由該方法的呼叫者來處理

     b:throw

         用在方法體內,跟的是異常物件名

         只能丟擲一個異常物件名

         表示丟擲異常,由方法體內的語句處理

 

###19.09_異常(finally關鍵字的特點及作用)

 A:finally的特點

     被finally控制的語句體一定會執行

     特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))

 B:finally的作用

     用於釋放資源,在IO流操作和資料庫操作中會見到

 C:案例演示

     finally關鍵字的特點及作用

return語句相當於是方法的最後一口氣,那麼在他將死之前會看一看有沒有finally幫其完成遺願,如果有就將finally執行後在徹底返回

    try {

System.out.println(10/0);

    } catch (Exception e) {

System.out.println("除數為零了");

System.exit(0); //finally不執行了 //退出jvm虛擬機器

return; //finally仍然執行

    } finally {

System.out.println("看看我執行了嗎");

    }

 

###19.10_異常(finally關鍵字的面試題)

 A:面試題1

     final,finally和finalize的區別

    * final可以修飾類,不能被繼承

* 修飾方法,不能被重寫

* 修飾變數,只能賦值一次

    * finally是try語句中的一個語句體,不能單獨使用,用來釋放資源

    * finalize是一個方法,當垃圾回收器確定不存在對該物件的更多引用時,由物件的垃圾回收器呼叫此方法。

 

 B:面試題2

     如果catch裡面有return語句,請問finally的程式碼還會執行嗎?如果會,請問是在return前還是return後。

public class Test1 {

    public static void main(String[] args) {

Demo d = new Demo();

System.out.println(d.method());

    }

}

class Demo {

    public int method() {

int x = 10;

try {

      x = 20;

      System.out.println(1/0);

     return x;

 } catch (Exception e) {

      x = 30;

     return x; //建立返回路徑,但還沒返回,執行finally後返回路徑那個還是30

 } finally {

      x = 40;

      //return x; 千萬不要在finally裡面寫返回語句,因為finally的作用是為了釋放資源,是肯定會執行的

      //如果在這裡面寫返回語句,那麼try和catch的結果都會被改變,所以這麼寫就是犯罪

 }

    }

}

    

###19.11_異常(自定義異常概述和基本使用)

 A:為什麼需要自定義異常

* 通過名字區分到底是神馬異常,有針對的解決辦法

     舉例:人的年齡

 B:自定義異常概述

     繼承自Exception

     繼承自RuntimeException

 C:案例演示

     自定義異常的基本使用

class AgeOutOfBoundsException extends Exception {

    public AgeOutOfBoundsException() {

super();

    }

    public AgeOutOfBoundsException(String message) {

super(message);

    }

}

 

###19.12_異常(異常的注意事項及如何使用異常處理)

 A:異常注意事項

     a:子類重寫父類方法時,子類的方法必須丟擲相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)

     b:如果父類丟擲了多個異常,子類重寫父類時,只能丟擲相同的異常或者是他的子集,子類不能丟擲父類沒有的異常

     c:如果被重寫的方法沒有異常丟擲,那麼子類的方法絕對不可以丟擲異常,如果子類方法內有異常發生,那麼子類只能try,不能throws

 B:如何使用異常處理

     原則:如果該功能內部可以將問題處理,用try,如果處理不了,交由呼叫者處理,這是用throws

     區別:

         後續程式需要繼續執行就try

         後續程式不需要繼續執行就throws

        

     如果JDK沒有提供對應的異常,需要自定義異常。

 

###19.13_異常(練習)

 鍵盤錄入一個int型別的整數,對其求二進位制表現形式

      如果錄入的整數過大,給予提示,錄入的整數過大請重新錄入一個整數BigInteger

      如果錄入的是小數,給予提示,錄入的是小數,請重新錄入一個整數

      如果錄入的是其他字元,給予提示,錄入的是非法字元,請重新錄入一個整數

    * 分析:

    * 1,建立鍵盤錄入物件

    * 2,將鍵盤錄入的結果儲存在String型別的字串中,儲存int型別中如果有不符合條件的直接報錯,無法進行後續判斷

    * 3,鍵盤錄入的結果轉換成int型別的資料,是正確的還是錯誤的

    * 4,正確的直接轉換

    * 5,錯誤的要進行對應判斷

   public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

System.out.println("請輸入一個整數:");

 

while(true) {

     String line = sc.nextLine(); //將鍵盤錄入的結果儲存在line中

try {

     int num = Integer.parseInt(line); //將字串轉換為整數

      System.out.println(Integer.toBinaryString(num));//將整數轉換為二進位制

     break; //跳出迴圈

 }catch(Exception e) {

     try {

new BigInteger(line);

   System.out.println("錄入錯誤,您錄入的是一個過大整數,請重新輸入一個整數:");

      }catch (Exception e2) { //alt + shif + z (try catch快捷鍵)

        try {

     new BigDecimal(line);

           System.out.println("錄入錯誤,您錄入的是一個小數,請重新輸入一個整數:");

 } catch (Exception e1) {

      System.out.println("錄入錯誤,您錄入的是非法字元,請重新輸入一個整數:");

  }

    }

}

    }

}

 

###19.14_File類(File類的概述和構造方法)

 A:File類的概述

     File更應該叫做一個路徑

         檔案路徑或者資料夾路徑  

         路徑分為絕對路徑和相對路徑

         絕對路徑是一個固定的路徑,從碟符開始

         相對路徑相對於某個位置,在eclipse下是指當前專案下,在dos下

     檢視API指的是當前路徑

     檔案和目錄路徑名的抽象表示形式

 B:構造方法

     File(String pathname):根據一個路徑得到File物件

C:案例演示

     File類的構造方法

 

    File file = new File("F:\\雙元課堂\\day19\\video\\001_今日內容.avi");

    System.out.println(file.exists());

 

    File file2 = new File("xxx.txt");

    System.out.println(file2.exists());

 

    File file3 = new File("yyy.txt");

    System.out.println(file3.exists());

 

     File(String parent, String child):根據一個目錄和一個子檔案/目錄得到File物件

    String parent = "F:\\雙元課堂\\day19\\video";

    String child = "001_今日內容.avi";

    File file = new File(parent,child);

    System.out.println(file.exists());

 

     File(File parent, String child):根據一個父File物件和一個子檔案/目錄得到File物件

    File parent = new File("F:\\雙元課堂\\day19\\video");

    String child = "001_今日內容.avi";

    File file = new File(parent, child);

    System.out.println(file.exists());

    System.out.println(parent.exists());

 

 ###19.15_File類(File類的建立功能)

 A:建立功能

     public boolean createNewFile():建立檔案 如果存在這樣的檔案,就不建立了

     public boolean mkdir():建立資料夾 如果存在這樣的資料夾,就不建立了

     public boolean mkdirs():建立資料夾,如果父資料夾不存在,會幫你創建出來

 B:案例演示

     File類的建立功能

 

     注意事項:

         如果你建立檔案或者資料夾忘了寫碟符路徑,那麼,預設在專案路徑下。

    File file = new File("yyy.txt");

    System.out.println(file.createNewFile()); //如果沒有就建立,返回true

 

    File file2 = new File("zzz");

    System.out.println(file2.createNewFile());

 

    File dir1 = new File("aaa");

    System.out.println(dir1.mkdir());

 

    File dir2 = new File("bbb.txt"); //這樣寫是可以的,資料夾也是可以有後綴的

    System.out.println(dir2.mkdir());

 

    File dir3 = new File("ccc\\ddd");

    System.out.println(dir3.mkdirs()); //建立多級目錄

        

###19.16_File類(File類的重新命名和刪除功能)

 A:重新命名和刪除功能

     public boolean renameTo(File dest):把檔案重新命名為指定的檔案路徑

     public boolean delete():刪除檔案或者資料夾

 B:重新命名注意事項

     如果路徑名相同,就是改名。

     如果路徑名不同,就是改名並剪下。

 C:刪除注意事項:

     Java中的刪除不走回收站。

     要刪除一個資料夾,請注意該資料夾內不能包含檔案或者資料夾

 

    File file1 = new File("ooo.txt");

    //File file2 = new File("xxx.txt"); //如果路徑名相同,就是改名。

    File file2 = new File("D:\\xxx.txt"); //如果路徑名不同,就是改名並剪下。

    System.out.println(file1.renameTo(file2));

 

    File file1 = new File("yyy.txt");

    System.out.println(file1.delete());

 

    File file2 = new File("aaa");

    System.out.println(file2.delete());

 

    File file3 = new File("ccc"); //如果刪除一個資料夾,那麼資料夾必須是空的

    System.out.println(file3.delete());

 

###19.17_File類(File類的判斷功能)

 A:判斷功能

     public boolean isDirectory():判斷是否是目錄

     public boolean isFile():判斷是否是檔案

     public boolean exists():判斷是否存在

     public boolean canRead():判斷是否可讀

     public boolean canWrite():判斷是否可寫

     public boolean isHidden():判斷是否隱藏

 B:案例演示

     File類的判斷功能

 

    File dir1 = new File("ccc");

    System.out.println(dir1.isDirectory()); //判斷是否是資料夾

 

    File dir2 = new File("zzz");

    System.out.println(dir2.isDirectory());

 

    System.out.println(dir1.isFile()); //判斷是否是檔案

    System.out.println(dir2.isFile());

 

    File file = new File("zzz");

    file.setReadable(false); //設定為不能讀

    System.out.println(file.canRead()); //true //windows系統認為所有的檔案都是可讀的

    file.setWritable(true);

    System.out.println(file.canWrite());//false //windows系統可以設定為不可寫

 

    File file2 = new File("aaa.txt");

    System.out.println(file2.isHidden()); //判斷是否是隱藏檔案

    System.out.println(file.isHidden());

 

###19.18_File類(File類的獲取功能)

 A:獲取功能

     public String getAbsolutePath():獲取絕對路徑

     public String getPath():獲取路徑

     public String getName():獲取名稱

     public long length():獲取長度。位元組數

     public long lastModified():獲取最後一次的修改時間,毫秒值

     public String[] list():獲取指定目錄下的所有檔案或者資料夾的名稱陣列

     public File[] listFiles():獲取指定目錄下的所有檔案或者資料夾的File陣列

 B:案例演示

     File類的獲取功能

    File file1 = new File("ccc.txt");

    File file2 = new File("D:\\雙元課堂\\day19\\ccc.txt");

    //System.out.println(file1.getAbsolutePath()); //獲取絕對路徑

    //System.out.println(file2.getAbsolutePath());//D:\\雙元課堂\\day19\\ccc.txt

 

    //System.out.println(file1.getPath()); //獲取構造方法中傳入路徑

    //System.out.println(file2.getPath());

 

    // System.out.println(file1.getName()); //獲取檔案或者檔案的名字

    // System.out.println(file2.getName());

    //

    // System.out.println(file1.length());//7位元組

 

    Date d = new Date(file1.lastModified()); //檔案的最後修改時間

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

    System.out.println(sdf.format(d));

 

    File dir = new File("D:");

 

    String[] arr = dir.list(); //僅為了獲取檔名

 

    for (String string : arr) {

System.out.println(string);

    }

    System.out.println("-------------");

    File[] subFiles = dir.listFiles();

 

    for (File file : subFiles) { //獲取檔案物件

System.out.println(file);

    }

 

###19.19_File類(輸出指定目錄下指定字尾的檔名)

 A:案例演示

     需求:判斷E盤目錄下是否有後綴名為.jpg的檔案,如果有,就輸出該檔名稱

    File dir = new File("E:\\");

 

    /*String[] arr = dir.list(); //獲取e盤下所有的檔案或資料夾

    for (String string : arr) {

    if(string.endsWith(".docx")) {

        System.out.println(string);

    }

    }*/

 

    File[] subFiles = dir.listFiles(); //獲取e盤下所有的檔案或資料夾物件

 

    for (File subFile : subFiles) {

        if(subFile.isFile() && subFile.getName().endsWith(".docx")) {

     System.out.println(subFile);

}

    }

 

###19.20_File類(檔名稱過濾器的概述及使用)

 A:檔名稱過濾器的概述

     public String[] list(FilenameFilter filter)

     public File[] listFiles(FileFilter filter)

 B:檔名稱過濾器的使用

     需求:判斷E盤目錄下是否有後綴名為.jpg的檔案,如果有,就輸出該檔名稱

 C:原始碼分析

     帶檔名稱過濾器的list()方法的原始碼

    File dir = new File("E:\\");

    String[] arr = dir.list(new FilenameFilter() {

        @Override

        public boolean accept(File dir, String name) {

            //System.out.println(dir);

            //System.out.println(name);

            File file = new File(dir, name);

           return file.isFile() && file.getName().endsWith(".docx");

         }

    });

    for (String string : arr) {

System.out.println(string);

    }

 

File類(遞迴)練習:

 5的階乘

  1、遞迴方法:

public class DiGui {

    public static void main(String[] args) {

        System.out.println(f(5));

    }

    

    public static long f(int n) {

        if(n <= 1) {

            return 1;

        } else {

        return n * f(n-1);

    }

    }

}

2、非遞迴:

public class WuJie {

    public static void main(String[] args) {

        long result = 1L;

        for(int i=1; i<=5; i++) {

            result*=i;

        }

        

        System.out.println(result);

    }

}      

拓展:

Throwable是一個怎樣的類?

     答:Throwable是java.lang包中一個專門用來處理異常的類。它有兩個子類,即Error 和Exception,它們分別用來處理兩組異常。
    Error用來處理程式執行環境方面的異常,比如,虛擬機器錯誤、裝載錯誤和連線錯誤,這類異常主要是和硬體有關的,而不是由程式本身丟擲的。
    Exception是Throwable的一個主要子類。Exception下面還有子類,其中一部分子類分別對應於Java程式執行時常常遇到的各種異常的處理,其中包括隱式異常。比如,程式中除數為0引起的錯誤、陣列下標越界錯誤等,這類異常也稱為執行時異常,因為它們雖然是由程式本身引起的異常,但不是程式主動丟擲的,而是在程式執行中產生的。Exception 子類下面的另一部分子類對應於Java程式中的非執行時異常的處理(在下圖中將它們直接屬於Exception了),這些異常也稱為顯式異常。它們都是在程式中用語句丟擲、並且也是用語句進行捕獲的,比如,檔案沒找到引起的異常、類沒找到引起的異常等。
    一些主要子類對應的異常處理功能簡要說明如下:
    ArithmeticException——由於除數為0引起的異常;
    ArrayStoreException——由於陣列儲存空間不夠引起的異常;
    ClassCastException—一當把一個物件歸為某個類,但實際上此物件並不是由這個類 建立的,也不是其子類建立的,則會引起異常;
    IllegalMonitorStateException——監控器狀態出錯引起的異常;
    NegativeArraySizeException—一陣列長度是負數,則產生異常;
    NullPointerException—一程式試圖訪問一個空的陣列中的元素或訪問空的物件中的 方法或變數時產生異常;
    OutofMemoryException——用new語句建立物件時,如系統無法為其分配記憶體空 間則產生異常;
    SecurityException——由於訪問了不應訪問的指標,使安全性出問題而引起異常;
    IndexOutOfBoundsExcention——由於陣列下標越界或字串訪問越界引起異常;
    IOException——由於檔案未找到、未開啟或者I/O操作不能進行而引起異常;
    ClassNotFoundException——未找到指定名字的類或介面引起異常;
    CloneNotSupportedException——一程式中的一個物件引用Object類的clone方法,但 此物件並沒有連線Cloneable介面,從而引起異常;
    InterruptedException—一當一個執行緒處於等待狀態時,另一個執行緒中斷此執行緒,從 而引起異常,有關執行緒的內容,將在下一章講述;
    NoSuchMethodException一所呼叫的方法未找到,引起異常;
    Illega1AccessExcePtion—一試圖訪問一個非public方法;
    StringIndexOutOfBoundsException——訪問字串序號越界,引起異常;
    ArrayIdexOutOfBoundsException—一訪問陣列元素下標越界,引起異常;
    NumberFormatException——字元的UTF程式碼資料格式有錯引起異常;
    IllegalThreadException—一執行緒呼叫某個方法而所處狀態不適當,引起異常;
    FileNotFoundException——未找到指定檔案引起異常;
    EOFException——未完成輸入操作即遇檔案結束引起異常。