目錄
一、異常
1.1異常的概述與分類
1.2JVM預設處理異常方法
1.3自定義異常處理方式
1.3.1 try catch處理算數異常
1.3.2 try catch處理多種異常
1.4編譯期異常和運作期異常
1.5Trowable的常見方法
1.6throws方式處理異常
1.7finally關鍵字
1.8關于finally的面試題
1.9自定義異常
1.10異常的注意事項
1.11異常練習
二、File類
2.1File概述與常用構造方法
2.2File類的建立功能
2.3File類的重命名和删除功能
2.4File類的判斷功能
2.5File類的擷取功能
2.6輸出盤符中指定檔案類型名稱
2.7檔案名稱過濾器
一、異常
1.1異常的概述與分類
異常就是java程式在運作過程中出現的一些錯誤。
異常最底層的就是Throwable,它又分為Error和Exception,
Error一般包括伺服器當機或者資料庫崩潰,我們隻需要重點了解Exception即可,下圖是部分異常的結構示意圖,
而RuntimeException為運作異常,又是Exception中的重點學習内容,一般在我們平時程式設計中很有可能會遇到,
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcsQXYtJ3bm9CXldWYtlWPzNXZj9mcw1ycz9WL49zdadHctxkMjRVTxgTMOhXUE1UeBRkTx0EVNZ3Yq1kdFRVT5VERNlHO5N2aGJjYzJEWkZXUYpVd1kmYr50MZV3aYJGdjdlYwlTeMZTTINGMShUYvwlbj5yZtlmbkN3YuQnclZnbvN2Ztl2Lc9CX6MHc0RHaiojIsJye.jpg)
1.2JVM預設處理異常方法
在程式産生了異常後,會由main函數收到這個異常,main函數一般有兩種解決方式:
- 自己将異常解決,然後程式繼續運作
- 自己沒有針對的解決辦法,就交給調用main函數的JVM來處理
JVM有一個預設的異常處理機制,就将該異常進行處理,
并且将該異常的名稱,異常的資訊,異常出現的位置列印在控制台上,同時程式也會停止運作。
比如我們讓除數為0看看會抛出什麼異常,
public class ExceptionTest {
public static void main(String[] args) {
System.out.println(div(1,0));
}
public static int div(int a,int b){
return a/b;
}
}
1.3自定義異常處理方式
異常處理的兩種方式:
- a:try+catch+finally
- try catch
- try catch finally
- try finally
- b:throws
其中try catch的方法是我們常用的方法,通過try catch處理異常後,程式可以正常執行,
try是用來檢測異常的,catch為捕獲異常,finally為釋放資源,我們來看看具體如何使用,
1.3.1 try catch處理算數異常
public class ExceptionTest {
public static void main(String[] args) {
try{
System.out.println(div(1,0));
}catch (ArithmeticException a){//捕獲算數異常
System.out.println("除數為0");
}
}
public static int div(int a,int b){
return a/b;
}
}
1.3.2 try catch處理多種異常
int a=10;
int b=0;
int arr[]={1,2,3,4,5};
try{
System.out.println(a/b);
System.out.println(arr[8]);
}catch (ArithmeticException |ArrayIndexOutOfBoundsException e){
System.out.println("程式出現異常");
}
我們還可以直接catch異常的底層Exception,這樣不用管是屬于哪種異常都可以直接擷取,
catch (Exception e){
System.out.println("程式出現異常");
}
1.4編譯期異常和運作期異常
Java中的異常被分為兩大類,編譯期異常和運作期異常,
所有的RuntimeException類及其子類的執行個體都被稱為運作期異常,其他的異常就是編譯期異常,
它們分别有以下幾個特點:
- 編譯期異常:Java程式必須顯示處理,否則程式就會發生錯誤,無法通過編譯
- 運作期異常:無需進行顯示處理,也可以和編譯期異常一樣處理
編譯期異常通俗來講就是程式在編寫時會提示紅色下劃波浪線的提示,如果不修改就無法通過編譯,
比如我們在讀檔案的時候,如果直接寫讀檔案語句,程式會提示有找不到檔案的異常,
意思是程式在運作之前不知道這個檔案是否可以找到,如果找不到的話程式就會出問題,是以要求我們提前顯示處理這個異常,
我們在try語句中寫這個操作就可以解決這個問題,
運作期異常就比較常見了,都是程式員經常會犯的錯誤,比如除數為0,數組越界等等。
1.5Trowable的常見方法
get Message()//擷取異常資訊,傳回字元串
toString()//擷取異常類名和異常資訊,傳回字元串
printStackTrace()//擷取異常類名和異常資訊,以及異常出現在程式中的位置,傳回值void
try{
FileInputStream file=new FileInputStream("test.txt");
}catch (FileNotFoundException fe){
System.out.println(fe.getMessage());
System.out.println("----------------------------------------");
System.out.println(fe.toString());
System.out.println("----------------------------------------");
fe.printStackTrace();
}
1.6throws方式處理異常
throws方式處理異常就是在程式可能會出錯的地方,throw一個建立的異常對象(例throw new Exception("***")),
需要注意的是如果抛出的是編譯期異常,則要在抛出的方法上加一個throws 異常對象類(例throws Exception),
這句話的意思是将異常抛給調用它的函數,如果是運作期異常則不需要在方法上加這句話,
如果在主函數中也加上了throws Exception,則就将異常抛給了java虛拟機JVM,通過預設的方法處理異常,
public class ExceptionTest {
public static void main(String[] args) throws Exception {
div(1,0);
}
public static int div(int a,int b) throws Exception {
if(b!=0){
return a/b;
}else{
throw new Exception("除數為0");
}
}
}
這裡細心的可能已經發現了在方法裡面我們寫的是throw,在方法上我們寫的是throws,它們主要有以下幾點差別:
- throws出現在方法函數頭,而throw出現在函數體。
- throws表示出現異常的一種可能性,并不一定會發生異常;throw則是抛出了異常,執行throw則一定抛出了某種異常對象
1.7finally關鍵字
finally關鍵字的特點為,被finally控制的語句一定會執行,
除非在執行到finally語句前JVM就已經退出了(System.exit(0)),
finally一般用于釋放資源,在IO流操作和資料庫操作中會經常見到,
try {
System.out.println(1/0);
}catch (Exception e){
System.out.println("除數為0");
return;//會在執行return語句之後執行finally控制的語句,然後再徹底結束方法
}finally {
System.out.println("finally控制語句");
}
可以看到就算在finally前面執行了return語句,finally控制的語句還是會執行,
程式在執行return語句結束方法時,會先看看有沒有finally語句,如果有則執行finally控制的語句,沒有就直接傳回。
1.8關于finally的面試題
1、final、finally和finalize的差別
- final為修飾符
- 可以修飾類,修飾的類不能被繼承
- 可以修飾方法,修飾的方法不能被重寫
- 可以修飾變量,修飾的變量值無法被更改
- finally為try中的一個語句體,不能單獨使用,用來釋放資源
- finalize是Obejct中的一個方法,當垃圾回收器确定不存在該對象的引用時,由對象的垃圾回收器調用此方法
2、若catch語句中有return語句,請問finally控制的代碼還會執行嗎?如果會是在return前還是return後執行?
通過1.7的例子我們可以知道就算在catch中有return語句,finally控制的代碼塊還是會執行,并且是在确定了return傳回的對象值并包裝好了之後執行finally的語句。
1.9自定義異常
java雖然已經給我們定義好了很多異常,但是我們在程式設計的時候還是會碰到很多問題,
比如我們定義了一個學生類,使用者在建立的時候輸入姓名和年齡,年齡的輸入就有限制條件,比如0到120歲,
最起碼不能是個負數,如果在給學生年齡指派的時候給了一個負數,我們就希望可以抛出一個異常然後輸出異常資訊,告訴我們是年齡輸入為負數這個錯誤
我們就可以自定義一個異常,繼承自Exception,如果想要的是運作期異常,那就繼承自RuntimeException,
運作期異常可以不用寫try和catch語句,不用對異常進行顯示處理,是以這裡我們自定義異常就繼承自RuntimeException,
public class ExceptionTest {
public static void main(String[] args){
Student stu=new Student();
stu.setAge(-1);
}
}
class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
class Student{
private String name;
private int age;
public Student(){}
public Student(String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public void setName(String name){
this.name=name;
}
public void setAge(int age) throws AgeOutOfBoundsException {
if(age>0 && age<120){
this.age=age;
}else{
throw new AgeOutOfBoundsException("年齡超出範圍");
}
}
}
1.10異常的注意事項
異常主要有以下幾個注意事項:
- 子類重寫父類方法時,子類的方法必須抛出相同的異常或者父類異常的子類
- 如果父類抛出了多個異常,子類重寫父類時,隻能抛出相同的異常或者多個異常的部分子集,不可以抛出父類沒有的異常
- 如果被重寫的方法沒有異常抛出,那麼子類的方法也不可以抛出異常,如果子類方法内有異常發生,子類隻可以try自己解決異常,不能throws抛出異常
在使用異常的時候,需要注意:
- 如果該功能内部可以解決異常,則用try語句;如果解決不了異常,則用throws抛出異常
- 後續程式如果需要繼續運作則用try,如果不需要繼續運作後續的代碼則用throws
1.11異常練習
要求:鍵盤錄入一個整數,求該整數的二進制形式,
如果錄入的整數過大,則提示使用者輸入的整數太大了,請重新錄入一個整數,
如果錄入的是小數,則提示使用者錄入的是小數,請重新錄入一個整數,
如果錄入的是其他字元,則提示使用者錄入的為非法字元,請重新錄入一個整數,
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Scanner;
public class ExceptionPractice {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("請輸入一個整數:");
while(true){
String input=scanner.nextLine();//先用字元串存儲輸入,避免輸入不是整數直接報錯
try {
int num=Integer.parseInt(input);//将字元串轉換為整數
System.out.println(Integer.toBinaryString(num));//将整數轉換為二進制形式
break;
}catch (Exception e1){
try{
new BigInteger(input);//若能裝入BigInteger,則說明不是非法字元和小數
System.out.println("錄入整數過大,請重新錄入一個整數:");
}catch (Exception e2){
try {
new BigDecimal(input);//若可以裝入BigDecimal,則說明不是非法字元
System.out.println("錄入的是小數,請重新錄入一個整數:");
}catch (Exception e3){
System.out.println("錄入的是非法字元,請重新錄入一個整數:");
}
}
}
}
}
}
二、File類
2.1File概述與常用構造方法
File類應該叫做一個路徑,是檔案和目錄路徑名的抽象表達形式,
路徑又分為絕對路徑和相對路徑,絕對路徑是從盤符開始的檔案路徑,
相對路徑是指相對于工程路徑下的路徑,比如目前工程路徑下的檔案我們可以直接寫檔案名不用加路徑,
我們首先學習一下File的幾個構造方法,
File(File parent,String child)//根據parent路徑名和child路徑名字元串建立一個新File執行個體
File(String pathname)//根據給定路徑名字元串建立一個新File執行個體
File(String parent,String child)//根據parent路徑名字元串和child路徑名字元串建立一個新File執行個體
File(URI uri)//通過給定的URI建立一個新的File執行個體
我們先學習以下前三個,看看具體如何使用,
File file1 = new File("data.txt");//相對路徑讀取檔案
System.out.println(file1.getName());
File file2 = new File("E:\\1program\\6Java\\JavaBasic\\01.HelloWorld\\src\\data.txt");//絕對路徑讀取檔案
System.out.println(file2.getName());
String parentStr="E:\\1program\\6Java\\JavaBasic\\01.HelloWorld\\src";
String childStr="data.txt";
File file3 = new File(parentStr,childStr);
System.out.println(file3.getName());
File parentFile=new File(parentStr);
File file4 = new File(parentFile,childStr);
System.out.println(file4.getName());
可以看到三種方式都正确擷取到了檔案的名字。
2.2File類的建立功能
public boolean createNewFile()//建立檔案,如果已經存在則不再建立
public boolean mkdir()//建立檔案夾,如果檔案夾已存在則不再建立
public boolean mkdirs()//建立檔案夾,如果父檔案夾也不存在,則會一起建立
我們來看看具體怎麼使用,
File file=new File("dataNew.txt");
System.out.println(file.createNewFile());//如果不存在dataNew.txt檔案,則建立一個dataNew.txt,否則不建立
File file1=new File("dirNew");
System.out.println(file1.mkdir());
File file2=new File("dirFather\\dirSon");
System.out.println(file2.mkdirs());
如果建立檔案或者檔案夾沒有寫盤符絕對路徑,那麼預設會在項目路徑下建立。
2.3File類的重命名和删除功能
public boolean renameTo(File dest)//把檔案重命名為指定的檔案路徑
public boolean delete()//删除檔案或者檔案夾
在重命名時,如果路徑名相同,那麼就是給檔案夾改名字,
如果路徑名不同,那麼就是改名之後将檔案夾剪切到目标路徑。
在删除的時候,檔案不會删除到資源回收筒中,是以删除後不能恢複,
如果要删除一個檔案夾,那麼該檔案夾中不能包含檔案或者檔案夾。
2.4File類的判斷功能
public boolean isDirectory()//判斷是否為目錄
public boolean isFile()//判斷是否為檔案
public boolean exists()//判斷是否存在
public boolean canRead()//判斷是否可讀
public boolean canWrite()//判斷是否可寫
public boolean isHidden()//判斷是否隐藏
我們可以通過方法設定檔案可讀和可寫性,
public boolean setReadable(boolean readable)//設定檔案可讀性(windows系統認為一切檔案都是可讀的)
public boolean setWriteable(boolean writeable)//設定檔案可寫性(windows系統可以設定檔案不可寫)
2.5File類的擷取功能
public String getAbsolutePath()//擷取絕對路徑
public String getPath()//擷取路徑(構造方法中傳入的路徑)
public String getName()//擷取名稱
public long length()//擷取檔案位元組的長度,位元組數
public long lastModified()//擷取最後一次的修改時間,毫秒值
public String[] list()//擷取指定目錄下的所有檔案和檔案夾的名稱數組
public File[] listFiles()//擷取指定目錄下的所有檔案和檔案夾的File數組
2.6輸出盤符中指定檔案類型名稱
import java.io.File;
public class FileTest {
public static void main(String[] args){
File dir=new File("F:\\");
String arr[]=dir.list();
for (String str : arr) {
if(str.endsWith(".cpp")) {
System.out.println(str);
}
}
}
}
結果驗證也是正确的,
還可以直接擷取所有的檔案和檔案夾,然後通過getName判斷,兩種方法都可以得到正确的結果。
File dir=new File("F:\\");
File subFiles[]=dir.listFiles();
for (File file : subFiles) {
if(file.isFile()&&file.getName().endsWith(".cpp")) {
System.out.println(file.getName());
}
}
2.7檔案名稱過濾器
檔案名稱過濾器就是給一個過濾器,然後尋找滿足條件的檔案,
主要有以下兩種過濾方法,第一個得到的是檔案的字元串數組,第二個得到的是檔案數組,
public String[] list(FilenameFilter filter)
public File[] listFiles(FileFilter filter)
我們看看如何具體使用,
File dir=new File("F:\\");
String arr[]=dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
File file=new File(dir,name);
return file.isFile()&&file.getName().endsWith(".cpp");
}
});
for (String str : arr) {
System.out.println(str);
}
我們看同樣也是輸出了字尾為cpp的檔案名,