天天看點

CGB-SE-day13day13

day13

抽象類

1. 半成品,是沒有完成的類
2. 抽象方法的作用:
	作為通用方法在父類中定義
	要求子類必須實作

3. final
	1. 常量, 值不可變
	2. 方法, 不能重寫
	3. 類, 不能繼承
	
4. static
	1. 靜态屬于類的
	2. 調用時,使用類名調用,也允許使用執行個體調用
	3. 靜态的初始化塊
		static{
			類加載時執行,隻執行一次
			}


5. 通路控制符
	1. public
	2. protected
	3. default
	4. private
6. 對象建立的過程 10步
	1. 


7. 接口
	1. 作用: 結構設計工具,解耦合,隔離實作
	2. interface
	3. implements
	4. 可以多實作,接口與接口之間可以多繼承
           

異常處理

封裝錯誤資訊的對象

錯誤資訊 有3點

1. 類型
	2. 提示資訊
	3. 行号
           

異常的繼承結構

Throwable
	| - Error 系統級錯誤, 無法處理,隻能盡量讓程式安全的退出.

	| - Exception 異常, 可修複的錯誤
			| - 其他 Exception

			| - RuntimeException
					|
					| - NullPointerException
					| - ArrayIndexOutOfBoundsException
					| - ArithmeticException 數學異常
					| - NumberFormatException
					| - ClassNotFoundException
					| - ClassCastException
					| - ...
           

異常的捕獲

try{
	捕獲
}catch(A異常類型){
	處理
}catch(B異常類型){
	處理
}catch(Exception e){
	父類型處理
} finally{
	不管處不出錯,都必須執行
}
           

throws

在方法上添加異常的抛出管道

void f() throws A,B,C{
}


出現異常, 異常必須處理,處理的方式有兩種
	1. catch
	2. throws
	
注: 在方法上, 存在預設的異常管道, 凡是RuntimeException下的異常都可以在不加管道的情況下,抛出
           

練習1, 異常

package day301;
    
    import java.util.Scanner;
    
    public class Test1 {
    	public static void main(String[] args) {
    		
    	while(true){
    		try {
    			f();
    			break;
    		} catch (ArrayIndexOutOfBoundsException e) {
    			System.out.println("輸入2個,不是一個");
    			
    		}catch(ArithmeticException e){
    			System.out.println("不嗯呢該除零");
    			
    		}catch (Exception e) {
    			System.out.println("出錯,請重試");
    			e.printStackTrace();
    			
    		}finally {
    			System.out.println("-----------------");
    			
    		}
    		
    	}
    				
    	}
    
    	private static void f() {
    		/*
    		 * 輸入2個整數,用 ,号隔開
    		 */
    		
    		System.out.println("請輸入2個整數,用 , 号隔開");
    		String s = new Scanner(System.in).nextLine();
    		//拆分,傳回一個數組
    		String[] a = s.split(",");
    		int m1 = Integer.parseInt(a[0]);
    		int m2 = Integer.parseInt(a[1]);
    		
    		int r=m1/m2;
    		System.out.println(r);
    		
    	}
    
    }
           

測試 throws

package day301;
    
    import java.io.File;
    import java.io.IOException;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Scanner;
    
    public class Test2 {
    	public static void main(String[] args) {
    		try {
    			f();
    		} catch (ParseException e) {
    			System.out.println("日期格式錯誤");
    			
    		} catch (IOException e) {
    			System.out.println("不能建立檔案");
    		}
    	}
    	private static void f() throws ParseException, IOException {
    		/*
    		 * 輸入日期(yyyy-MM-dd) "2919-4-1"
    		 * 
    		 * SimpleDateFormat 日期格式工具,把字元串解析成Date
    		 * 
    		 * Date 執行個體中,封裝的是時間的毫秒值
    		 * 取出毫秒值:3656456544
    		 * 建立一個檔案 d:\3656456544.txt 檔案
    		 * 
    		 */
    		System.out.println("輸入日期(yyyy-MM-dd): ");
    		String s = new Scanner(System.in).nextLine();
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    		//強制處理異常
    		//必須事先考慮異常如何考慮,給出處理方案
    		Date d = sdf.parse(s);
    		String path="d:\\"+d.getTime()+".txt";
    		
    		File file = new File(path);
    		file.createNewFile();
    		System.out.println("檔案已經建立"+path);
    		
    	}
    
    }
           

RuntimeException和其他 Exception差別

RuntimeException: 稱為"非檢查異常"
編譯期不會檢查這種異常,不便攜處理代碼也可以

其他Exception 稱為 "檢查異常"
編譯期會檢查這種異常,有沒有處理代碼,沒有代碼,編譯不會通過

兩種處理異常的方式: catch , throws 
RuntimeException 就算不寫預設也會添加管道.
           

catch 和 throws 如何選擇?

如果是在底層代碼出現的錯誤,一般要向上層抛出,在調用路徑中,選擇一個合适的位置捕獲處理.

如果經驗不足,不知道如何選擇 catch 還是 throws, 就要用 throws,不能随便 catch.
           

throw

手動抛出異常,執行異常的抛出動作

	當程式出現邏輯錯誤 ,而且不自動建立異常,可以手動建立異常對象,并手動抛出

	throw e,優點相當于 return e ;的感覺


#### 測試 throw


package day301;

import java.util.Scanner;

public class test3 {
	public static void main(String[] args) {
		f();
	}

	private static void f() {
		/*
		 * 5345/0  出現異常 ArithmeticException
		 * 
		 * 32.5632 /0  -->Infinity 無窮大值 ,特殊值
		 * 不出錯, 沒有提示異常
		 * Infinity 沒有意義,我們需要處理這種資料異常
		 */
		
		System.out.println("輸入兩個浮點數:");
		double a = new Scanner(System.in).nextDouble();
		double b = new Scanner(System.in).nextDouble();
		
		try {
			double c=divide(a,b);
			System.out.println(c);
			
		} catch (ArithmeticException e) {
			System.out.println("不能除零,是我們的錯");
			e.printStackTrace();
		}
		
	}

	private static double divide(double a, double b) {
			if(b==0){
				ArithmeticException e = 
						new ArithmeticException(" / by zero ");
				throw e;
			}
		return a/b ;
	}

}
           

異常包裝 捕獲的異常,包裝成另一種類型在抛出

為什麼要包裝後在抛出?

異常包裝使用用場景:
	1. 不能抛出的類型,包裝成能抛出的類型
	2. 異常的簡化

為什麼不能抛出? 不是加個管道就可以抛出了嗎?
  如: 	方法重寫時,異常管道,不能比父類方法的管道多.
           

異常包裝的測試:

package day301;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test4 {
	public static void main(String[] args) {
		Student s = new Student("張三", "asda-06-12");
		System.out.println(s);
		
	}

}

class Student{
	String name;
	String  birthday; //"1945-12-10"
	
	public Student(String name, String  birthday) {
		super();
		this.name = name;
		this.birthday = birthday;
	}
	@Override
	public String toString() {
		// 張三 ,7854642131321(毫秒值)
		// SimpleDateFormat 解析成Date 執行個體
		// 從Date 中再取出毫秒值
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date d = sdf.parse(birthday);
			return  name+","+d.getTime();
			
		} catch (ParseException e) {
			/*
			 * Parseexception 是抛不出去的, 因為他不是RuntimeException類型的
			 * 而且 也不能 throws 加管道,因為 toString()是重寫父類object的,
			 * 父類中的toString() 沒有聲明管道,隻有預設的RuntimeException管道.
			 * 是以需要把他 包裝成 可以抛出的類型.
			 */
			throw new RuntimeException(e);
		
			
		}
		
	}

}


 如果出現異常,他的異常資訊:

Exception in thread "main" java.lang.RuntimeException: java.text.ParseException: Unparseable date: "asda-06-12"
	at day301.Student.toString(Test4.java:42)
	at java.lang.String.valueOf(String.java:2982)
	at java.io.PrintStream.println(PrintStream.java:821)
	at day301.Test4.main(Test4.java:10)
Caused by: java.text.ParseException: Unparseable date: "asda-06-12"
	at java.text.DateFormat.parse(DateFormat.java:366)
	at day301.Student.toString(Test4.java:32)
	... 3 more
           

自定義異常類型

業務中的錯誤情況,用現有的異常類型是無法表示的,
如 轉賬失敗, 就沒有合适的異常來表示

我們的自定義異常 隻不過是起一個符合這個異常描述的名字,我們也隻是需要一個合适的名字.

轉賬異常:
ZhuanZhangShiBaiException

使用者名錯誤
usernameNotFoundException

密碼錯誤
WrongPassworldException


自定義異常:
	1. 起一個合适的類名
	2. 選擇一個合适的異常父類, 可以繼承runtimeException或者 Exception都可以,但注意的是 RuntimeException 是預設的管道,不用throws也可以抛出. 
	3. 添加合适的構造方法
           

自定義異常 測試

自定義 2個異常, 
一個使用者名異常,
一個密碼異常.
如下:建立類:
           
package day301;

public class usernameNotFoundException  extends Exception{
/*
 * 在寫自定義異常的構造時 ,參考父類的寫法,
 * Shift+Alt+ s  -----> 
 * 
 */
	public usernameNotFoundException() {
		super();
	}

	public usernameNotFoundException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public usernameNotFoundException(String message, Throwable cause) {
		super(message, cause);
	}

	public usernameNotFoundException(String message) {
		super(message);
	}

	public usernameNotFoundException(Throwable cause) {
		super(cause);
	}
	
		
}
           
package day301;

public class WrongPassworldException extends Exception{

	public WrongPassworldException() {
		super();
	}

	public WrongPassworldException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public WrongPassworldException(String message, Throwable cause) {
		super(message, cause);
	}

	public WrongPassworldException(String message) {
		super(message);
	}

	public WrongPassworldException(Throwable cause) {
		super(cause);
	}
	
}
           
package day301;

import java.util.Scanner;

public class Test5 {
	public static void main(String[] args) {
		System.out.println("使用者名: ");
		String n = new Scanner(System.in).nextLine();
		System.out.println("密碼: ");
		String p = new Scanner(System.in).nextLine();
		try {
			login(n,p);
			System.out.println("登陸成功");
		} catch (usernameNotFoundException e) {
			System.out.println("使用者名不存在");
		}catch (WrongPassworldException e) {
			System.out.println("密碼錯誤");
		}
		
		
	}

	private static void login(String n, String p) throws usernameNotFoundException, WrongPassworldException  {
		//  "abc" ,"123"
		if (!n.equals("abc")) {
			throw new usernameNotFoundException();
		}
		if (!p.equals("123")) {
			throw new WrongPassworldException();
		}
		
		
		
	}

}
           

IO

Input/ Output
輸入 / 輸出

輸入: 外部資料,讀取到記憶體,有程式進行處理
輸出: 記憶體中的資料,向外部輸出
           

java.io 包

1. File
2. InputStream /OutputStream
3. FileInputStream/ fileOutputStream
4. ObjectInputStream /ObjectOutputStream
5. Reader /Writer
6. InputStreamReader /OutputSteramWriter
7. BufferedReader
8. PrintWriter
           

File 類

用來封裝磁盤路徑字元串

File 執行個體={ path: "d:\a.txt"}

可以封裝:
	1. 檔案路徑
	2. 檔案夾路徑
	3. 不存在的路徑
	
内部提供了一些方法:
           

檔案或檔案夾屬性方法:

1. getName() 擷取檔案名
2. getParent()  擷取父檔案夾 (路徑)
3. getAbsolutePath() 完整路徑 ,絕對路徑
4. exists() 是否存在,判斷這個路徑是否存在, 傳回值 boolean
5. isFile() 是否是檔案
6. isDirectory() 是否是檔案夾
7. length()  擷取檔案的位元組量, 對檔案夾無效
           

屬性方法測試: