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

19 異常&IO(File類)

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

  • A:異常的概述
    • 異常就是Java程式在執行過程中出現的錯誤。
  • B:異常的分類
    • 通過API檢視Throwable,異常最頂層的
    • Error
      • 伺服器宕機,資料庫崩潰等
    • Exception
      C:異常的繼承體系
    • Throwable
      • Error
      • Exception
        • RuntimeException(執行時異常,特殊,其他都是編譯時異常)

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:釋放資源

	public static void main(String[] args) {
		Demo2 d = new Demo2();
		try{
			int x = d.div(10, 0);
			System.out.println(x);
		}catch(ArithmeticException a) {		//可能出現的異常型別,ArithmeticException a = new ArithmeticException();
			System.out.println("出錯了,除數為零了");
		}
		
		System.out.println("1111111111111111");//當通過trycatch將問題處理了,程式會繼續執行
	}

}

class Demo2 {
	/*
	 * 除法運算
	 */
	public int div(int a,int b) {		//a = 10,b = 0
		return a / b;					// 10 / 0  被除數是10,除數是0當除數是0的時候違背了算數運演算法則,丟擲異常
										//new ArithmeticException("/ by zero");
	}

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

  • A:案例演示
    • try…catch的方式處理多個異常
  • 安卓,客戶端開發,如何處理異常?try{}catch(Exception e){}
    ee,服務端開發,一般都是底層開發,從底層向上拋,需要多寫幾個catch
    try後面如果跟多個catch,那麼小的異常放前面,大的異常放後面,根據多型的原理,如果大的放前面,就會將所有的子類物件接收
    後面的catch就沒有意義了
public static void demo1() {
		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("over");
	}
  • JDK7以後處理多個異常的方式及注意事項
public static void main(String[] args) {
		int a = 10;
		int b = 0;
		int[] arr = {11,22,33,44,55};
		
		//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:案例演示
    • 編譯期異常和執行期異常的區別

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

  • A:Throwable的幾個常見方法
    • a:getMessage()
      • 獲取異常資訊,返回字串。
    • b:toString()
      • 獲取異常類名和異常資訊,返回字串。
    • c:printStackTrace()
      • 獲取異常類名和異常資訊,以及異常出現在程式中的位置。返回值void。
  • B:案例演示
    • Throwable的幾個常見方法的基本使用
	public static void main(String[] args) {
		try {
			System.out.println(1/0);
		} catch (Exception e) {			//Exception e = new ArithmeticException("/ by zero");
			//System.out.println(e.getMessage());		//獲取異常資訊
			//System.out.println(e); 		//呼叫toString方法,列印異常類名和異常資訊
			e.printStackTrace();		//jvm預設就用這種方式處理異常 
		}
	}

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

  • A:throws的方式處理異常
    • 定義功能方法時,需要把出現的問題暴露出來讓呼叫者去處理。
    • 那麼就通過throws在方法上標識。
  • B:案例演示
    • 舉例分別演示編譯時異常和執行時異常的丟擲
    • 編譯時異常的丟擲必須對其進行處理
    • 執行時異常的丟擲可以處理也可以不處理
public static void main(String[] args) throws Exception {  //主函式中也要進行宣告
		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) throws Exception {    //丟擲異常時要在方法上進行宣告
		if(age >0 && age <= 150) {
			this.age = age;
		}else {
			throw new Exception("年齡非法");
		}
	}
	
	
}

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

  • A:throw的概述
    • 在功能方法內部出現某種情況,程式不能繼續執行,需要進行跳轉時,就用throw把異常物件丟擲。
  • B:案例演示
    • 分別演示編譯時異常物件和執行時異常物件的丟擲
  • C:throws和throw的區別
    • a:throws
      • 用在方法聲明後面,跟的是異常類名
      • 可以跟多個異常類名,用逗號隔開
      • 表示丟擲異常,由該方法的呼叫者來處理
    • b:throw
      • 用在方法體內,跟的是異常物件名
      • 只能丟擲一個異常物件名
      • 表示丟擲異常,由方法體內的語句處理
	        //Exception e = new Exception("年齡非法");
			//throw e;
			
			throw new AgeOutOfBoundsException("年齡非法");

throw兩種寫法

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

  • A:finally的特點
    • 被finally控制的語句體一定會執行
    • 特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))
  • B:finally的作用
    • 用於釋放資源,在IO流操作和資料庫操作中會見到
  • C:案例演示
    • finally關鍵字的特點及作用

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

  • A:面試題1

    • final,finally和finalize的區別

    final可以修飾類,不能被繼承
    修飾方法,不能被重寫
    修飾變數,只能賦值一次

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

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

  • B:面試題2

    • 如果catch裡面有return語句,請問finally的程式碼還會執行嗎?如果會,請問是在return前還是return後。
public static void main(String[] args) {
		Demo d = new Demo();
		System.out.println(d.method());//30
	}

}

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;    //執行return時已經建立好了返回路徑。即使執行了finally,x的返回值不會再改變
		} finally {
			x = 40;
			//return x;					千萬不要在finally裡面寫返回語句,因為finally的作用是為了釋放資源,是肯定會執行的
										//如果在這裡面寫返回語句,那麼try和catch的返回值都會被改變
		}
	}

先執行finally再執行return

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

  • A:為什麼需要自定義異常(更準確的定位到錯誤)
    • 舉例:人的年齡
  • B:自定義異常概述
    • 繼承自Exception
    • 繼承自RuntimeException
  • C:案例演示
    • 自定義異常的基本使用
class AgeOutOfBoundsException extends Exception {

	public AgeOutOfBoundsException() {
		super();
		
	}

	public AgeOutOfBoundsException(String message) {
		super(message);
		
	}
public void setAge(int age) throws AgeOutOfBoundsException {
		if(age >0 && age <= 150) {
			this.age = age;
		}else {
			throw new AgeOutOfBoundsException("年齡非法");
		}
	}

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物件
public static void demo1() {
		File file = new File("F:\\雙元課堂\\day19\\video\\001_今日內容.avi");//要加字尾
		System.out.println(file.exists());//true
		
		File file2 = new File("xxx.txt");
		System.out.println(file2.exists());//true
		
		File file3 = new File("yyy.txt");
		System.out.println(file3.exists());//false
	}
  • File(String parent, String child):根據一個目錄和一個子檔案/目錄得到File物件
public static void demo2() {
		String parent = "F:\\雙元課堂\\day19\\video";
		String child = "001_今日內容.avi";
		File file = new File(parent,child);
		System.out.println(file.exists());//true
	}
  • File(File parent, String child):根據一個父File物件和一個子檔案/目錄得到File物件
public static void main(String[] args) {
		File parent = new File("F:\\雙元課堂\\day19\\video");//將父級路徑封裝成物件
		String child = "001_今日內容.avi";
		File file = new File(parent, child);
		System.out.println(file.exists());//true
		System.out.println(parent.exists());//true
	}
  • C:案例演示
    • File類的構造方法

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

  • A:建立功能
    • public boolean createNewFile():建立檔案 如果存在這樣的檔案,就不建立了
    • public boolean mkdir():建立資料夾 如果存在這樣的資料夾,就不建立了
    • public boolean mkdirs():建立資料夾,如果父資料夾不存在,會幫你創建出來
  • B:案例演示
    • File類的建立功能

    • 注意事項:

      • 如果你建立檔案或者資料夾忘了寫碟符路徑,那麼,預設在專案路徑下。
public static void main(String[] args) throws IOException {
		//demo1();
		File dir1 = new File("aaa");   //資料夾建立在專案下
		System.out.println(dir1.mkdir());  //建立成功返回true
		
		File dir2 = new File("bbb.txt");				//這樣寫是可以的,資料夾也是可以有後綴的
		System.out.println(dir2.mkdir());
		
		File dir3 = new File("ccc\\ddd");  
		System.out.println(dir3.mkdirs()); 				//建立多級目錄
	}

	public static void demo1() throws IOException {
		File file = new File("yyy.txt");
		System.out.println(file.createNewFile());			//如果沒有就建立,返回true,如果有就不建立,返回false
		
		File file2 = new File("zzz");
		System.out.println(file2.createNewFile());//不加字尾也能建立
	}

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

  • A:重新命名和刪除功能
    • public boolean renameTo(File dest):把檔案重新命名為指定的檔案路徑
public static void demo1() {
		File file1 = new File("ooo.txt");
		File file2 = new File("D:\\xxx.txt");
		System.out.println(file1.renameTo(file2));
	}
  • public boolean delete():刪除檔案或者資料夾
public static void main(String[] args) {
		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());
	}
  • B:重新命名注意事項
    • 如果路徑名相同,就是改名。
    • 如果路徑名不同,就是改名並剪下。
  • C:刪除注意事項:
    • Java中的刪除不走回收站。
    • 要刪除一個資料夾,請注意該資料夾內不能包含檔案或者資料夾

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

  • A:判斷功能
    • public boolean isDirectory():判斷是否是目錄
    • public boolean isFile():判斷是否是檔案
    • public boolean exists():判斷是否存在
public static void demo1() {
		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());
	}
  • public boolean canRead():判斷是否可讀
  • public boolean canWrite():判斷是否可寫
  • public boolean isHidden():判斷是否隱藏
public static void main(String[] args) {
		//demo1();
		File file = new File("zzz");
		file.setReadable(false);  //設定可讀性,但是windows系統沒意義
		System.out.println(file.canRead()); 			//windows系統認為所有的檔案都是可讀的
		file.setWritable(true);  //設定可寫性
		System.out.println(file.canWrite()); 			//windows系統可以設定為不可寫
		
		File file2 = new File("aaa.txt");
		System.out.println(file2.isHidden());			//判斷是否是隱藏檔案
		System.out.println(file.isHidden());
	}
  • B:案例演示
    • File類的判斷功能

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類的獲取功能
public static void main(String[] args) {
		//demo1();
		File dir = new File("F:/雙元課堂/day19/video");
		String[] arr = dir.list();						//僅為了獲取檔名
		
		for (String string : arr) {
			System.out.println(string);
		}
		
		File[] subFiles = dir.listFiles();
		
		for (File file : subFiles) {					//獲取檔案物件
			System.out.println(file);
		}
 	}

	public static void demo1() {
		File file1 = new File("ccc.txt");
		File file2 = new File("D:\\雙元課堂\\day19\\ccc.txt");
		//System.out.println(file1.getAbsolutePath());			//獲取絕對路徑
		//System.out.println(file2.getAbsolutePath());
		
		//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());
		
		Date d = new Date(file1.lastModified());				//檔案的最後修改時間
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		System.out.println(sdf.format(d));
	}

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

  • A:案例演示
    • 需求:判斷E盤目錄下是否有後綴名為.jpg的檔案,如果有,就輸出該檔名稱
public static void main(String[] args) {
		File dir = new File("E:\\");
		
//		String[] arr = dir.list();					//獲取e盤下所有的檔案或資料夾
//		for (String string : arr) {
//			if(string.endsWith(".jpg")) {
//				System.out.println(string);
//			}
//		}
		
		File[] subFiles = dir.listFiles();			//獲取e盤下所有的檔案或資料夾物件
		
		for (File subFile : subFiles) {
			if(subFile.isFile() && subFile.getName().endsWith(".jpg")) {
				System.out.println(subFile);
			}
		}
	}

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

  • A:檔名稱過濾器的概述
    • public String[] list(FilenameFilter filter)
    • public File[] listFiles(FileFilter filter)
  • B:檔名稱過濾器的使用
    • 需求:判斷E盤目錄下是否有後綴名為.jpg的檔案,如果有,就輸出該檔名稱
  • C:原始碼分析
    • 帶檔名稱過濾器的list()方法的原始碼
	public static void main(String[] args) {
		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(".jpg");
			}
		});
		
		for (String string : arr) {
			System.out.println(string);
		}
	}