一、關于異常的練習
package com.exercise.trycatch;
import java.util.Scanner;
/**
* @author alice_huijing
* @version 1.0
*/
public class TryCatchExercise01 {
}
// 第一道題
//class Exception01 {
// public static int method() {
// try {
// String[] names = new String[3]; // names指向了一個數據,但是里面為空null
// if (names[1].equals("tom")) { // null. 出現空指針異常,會在3捕獲
// System.out.println(names[1]);
// } else {
// names[3] = "hspedu";
// }
// return 1;
// } catch (ArrayIndexOutOfBoundsException e) {
// return 2;
// } catch (NullPointerException e) { // 捕獲,這里只是捕獲了,但是并不會返回
// return 3;
// } finally { // 但是finally是必須執行的,所以必須會執行finally下面的語句,返回4
// return 4;
// }
// }
// public static void main(String[] args) {
// System.out.println(method()); // 4
// }
//}
// 第二道題
//class Exception02 {
// public static int method() {
// int i = 1;
// try {
// i++; // i等于2
// String[] names = new String[3]; // names->null null null
// if (names[1].equals("tom")) { // 空指針異常,下方代碼不會執行
// System.out.println(names[1]);
// } else {
// names[3] = "hspedu";
// }
// return 1;
// } catch (ArrayIndexOutOfBoundsException e) {
// return 2;
// } catch (NullPointerException e) { // 執行空指針異常的代碼先加之后返回,i等于3,因為finally必須要執行不會返回
// return ++i;
// } finally {
// return ++i; // 先加,i等于4,然后返回4
// }
// }
// public static void main(String[] args) {
// System.out.println(method()); // 4
// }
//}
// 第三題
//class ExceptionExe01 {
// public static int method() {
// int i = 1;
// try {
// i++; // i等于2
// String[] names = new String[3]; // names -> null,null,null
// if (names[1].equals("tom")) { // null. 空指針異常
// System.out.println(names[1]);
// } else {
// names[3] = "hspedu";
// }
// return 1;
// } catch (ArrayIndexOutOfBoundsException e) {
// return 2;
// } catch (NullPointerException e) { // i等于3,返回3,底層保存在一個臨時變量temp中,繼續往下執行finally,最后回來返回
// return ++i;
// } finally {
// ++i; // 必須要執行,i等于4
// System.out.println("i="+i); // i=4
// }
// }
// public static void main(String[] args) {
// System.out.println(method()); // 3
// }
//}
/*
try-catch異常處理
try-catch-finally執行順序小結
1、如果沒有出現異常,則執行try塊中所有的語句,不執行catch塊中的語句,如果有finally,最后還要繼續執行finally里面的語句
2、如果出現異常,則try塊中異常發生后,剩下的語句不再執行。將執行catch塊中的語句,如果有finally,最后還要執行finally里面的語句。
課后練習題:如果用戶輸入的不是一個整數,就提示他反復輸入,直到輸入一個整數為止。
將輸入的字符串轉換成整數,如果不能轉換就是產生了異常,捕獲然后處理即可。
思路分析:
1、創建一個Scanner對象
2、使用無限循環,去接收一個輸入
3、然后將該輸入的值,轉換成一個int
4、如果在轉換的時候,拋出異常,說明輸入的內容不是一個可以轉換成int的內容
5、如果沒有拋出異常,則break,該循環。
*/
class Test {
public void TryCatch() {
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while (true) {
System.out.print("請輸入一個整數:");
inputStr = scanner.next();
try {
num = Integer.parseInt(inputStr); // 這里可能會拋出異常
break;
} catch (NumberFormatException e) {
System.out.println("你輸入的不是一個整數!!");
}
}
System.out.println("你輸入的是->" + num);
}
}
二、throws異常處理
package com.exercise.trycatch;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author alice_huijing
* @version 1.0
*/
public class Throws02 {
public static void main(String[] args) {
}
public void f1() throws FileNotFoundException {
// 創建一個文件對象,因為這里是一個編譯異常,所以這里需要明確的處理。可以使用try catch處理,或者是拋出
// 讓誰處理?使用throws拋出異常,讓調用f1方法的調用者來進行處理。
FileInputStream fis = new FileInputStream("d://aa.txt"); // 這是一個編譯時異常
// 并且因為Exception是FileNotFoundException的父類,也可以拋出的是Exception
//throws關鍵字后面也可以是一個異常列表,即拋出多個異常,異常之間使用逗號分割
//FileNotFoundException,NullPointerException,當然,因為這三個異常都是Exception的子類,所以只寫
//Exception都可以拋出
}
}
/*
throws異常處理
基本介紹
1、如果一個方法中的語句執行時可能生成某種異常,但是并不能確定如何處理這種異常,則此方法因顯示地聲明拋出異常,表示該方法將
不對這些異常進行處理,而該方法的調用者負責處理。
2、在方法聲明中使用throws語句可以聲明拋出異常的列表,throws后面的異常類型可以是方法中產生的異常類型,也可以是它的父類。
*/
package com.exercise.trycatch;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author alice_huijing
* @version 1.0
*/
public class Throws03 {
public static void main(String[] args) {
}
public void f2() {
// 2、對于運行時異常,程序中如果沒有處理,默認就是throws的方式來處理
int n1 = 10;
int n2 = 0;
double res = n1 / n2;
// 我們自己是知道這里存在算術異常的,但是這里好像爆紅,其實默認是使用throws的方式來進行了處理相當于
// public void f2() throws ArithmeticException,默認這邊是有這樣一句話
// 我們怎么知道確實是有這樣一句話呢?
// 當我們在main中調用f2的時候實際上這里會將異常拋出給到main,而
// 在main中相當于也是默認有這樣的一句話throws ArithmeticException
// 最終拋給JVM,而JVM就不會有捕獲這樣的操作,JVM直接簡單粗暴的將你的程序掛掉
}
public static void f1() throws FileNotFoundException {
// 這里直接調用f3()會報錯
// 1、因為f3這個方法拋出的是一個編譯異常必須要求處理
// 2、這個時候就需要處理這個異常,可以捕獲這個異常或者是繼續拋出這個異常
f3();
// try {
// f3();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
}
public static void f3() throws FileNotFoundException {
FileInputStream fis = new FileInputStream("d://aa.txt");
}
public static void f4() {
// 這里調用f5是可以的
// 因為f5是一個運行異常的拋出
// 在java中運行異常不強制要求處理,所以有默認處理機制
// 相當于f4這里默認拋出throws ArithmeticException
f5();
}
public static void f5() throws ArithmeticException {
}
}
/*
throws異常處理的注意事項和使用細節
1、對于編譯異常,程序中必須要處理,比如try-catch或者throws來處理
2、對于運行時異常,程序中如果沒有處理,默認就是throws的方式來處理
3、子類重寫父類的方法時,對拋出異常的規定:子類重寫的方法,所拋出的異常類型要么和父類拋出的異常一致
要么為父類拋出的異常的類型的子類型
4、在throws過程中,如果有方法try-catch,就相當于處理異常,就可以不必throws
*/
class Father {
public void method() throws RuntimeException {
}
}
class Son extends Father {
@Override
public void method() throws NullPointerException {
/*
子類重寫了父類的方法,對拋出的異常的規定,子類重寫的方法,
所拋出的異常類型要么和父類拋出的異常一致,要么為父類拋出的異常的類型的子類型
*/
}
}
三、自定義異常
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
public class Customize04 {
public static void main(String[] args) {
int age = 180;
// 要求范圍在18-120之間,否則拋出一個自定義異常
if (!(age >= 18 && age <= 120)) {
// Exception in thread "main" com.exercise.trycatch.AgeException: 年齡需要在18~120之間
throw new AgeException("年齡需要在18~120之間");
}
System.out.println("你的年齡范圍正確。");
}
}
// 自定義一個異常
// 一般情況下我們自定義異常都是繼承運行時異常
// 將自定義異常做成運行時異常,好處是,我們可以使用默認的處理比較方便
// 如果繼承的是Exception,那么就是一個編譯異常,不是不可以,如果繼承的是這個,那么
// 我們在main中調用的時候main上面也需要顯示的寫throws AgeException,因為編譯異常需要要求程序員處理
// 沒有默認的,而運行時異常有默認的更加方便。
class AgeException extends RuntimeException {
public AgeException(String message) {
// 可以通過構造器設置內容
super(message);
/*
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
最終到達detailMessage,最終將異常輸出出來
*/
}
}
/*
自定義異常
基本概念
當程序中出現了某些錯誤,但是該錯誤信息并沒有在Throwable子類中描述處理,這個時候可以自己設計異常類,
用于描述該錯誤信息。
自定義異常的步驟
1、定義類:自定義異常類名(程序員自己寫)需要繼承Exception或者是RuntimeException
2、如果繼承Exception,屬于的是編譯異常
3、如果繼承RuntimeException屬于運行異常(一般來說,繼承RuntimeException)
*/
四、throw和throws的區別
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
public class throwAndThrows05 {
// public static void main(String[] args) {
//
// }
}
/*
throw和throws的區別
throws的意義:異常處理的一種方式
位置:方法聲明處
后面跟的東西:異常類型
throw的意義:手動生成異常對象的關鍵字
位置:方法體中
后面跟的東西:異常對象
*/
class ReturnExceptionDemo {
static void methodA() {
try {
System.out.println("進入方法A");
throw new RuntimeException("制造異常"); // 被調用這個方法的調用者捕獲
} finally {
System.out.println("使用A方法的finally");
}
}
static void methodB() {
try {
System.out.println("進入方法B");
return ; // 不會馬上執行,finally先執行
} finally {
System.out.println("調用B方法的finally");
}
}
public static void main(String[] args) {
try {
ReturnExceptionDemo.methodA(); // 在這里捕獲這個運行時異常
} catch (Exception e) {
System.out.println(e.getMessage()); // 制造異常,這個是異常信息
}
ReturnExceptionDemo.methodB();
}
}
/*
進入方法A
使用A方法的finally
制造異常
進入方法B
調用B方法的finally
*/
五、練習
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
public class Homework06 {
public static void main(String[] args) {
try { // 將可能會產生異常的代碼塊進行包裹
if (args.length != 2) {
throw new ArrayIndexOutOfBoundsException("參數個數不正確。");
} // 1.因為要接收命令行的是兩個參數,限定,這里可能會拋出第一個異常
// 2將接收到的兩個字符串轉換成整數,因為當前數組是String[] args,這里可能不能轉換也會拋出一個異常
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
// 3接下來是計算,可能產生除零的異常
double res = cal(n1, n2);
System.out.println("結算結果是="+res);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
} catch (NumberFormatException e) {
System.out.println("參數格式不正確,需要輸入整數");
} /*這里有一個異常IDEA檢測不到,就是這里的除零的異常,所以無法自動生成*/
catch (ArithmeticException e) {
System.out.println("出現了除0的異常");
}
}
public static double cal(int n1, int n2) {
return n1 / n2; // 除零出現異常自動往上面丟
}
}
// 第一題
/*
1、編寫應用程序EcmDef.java,接收命令行的兩個參數(整數),計算兩數相除。
2、計算兩個數相除,要求使用方法cal(int n1, int n2)
3、對數據格式不正確,缺少命令行參數,除以0進行異常處理。
*/
package com.exercise.trycatch;
/**
* @author alice_huijing
* @version 1.0
*/
/*
說出以下代碼是否會發生異常,如果會,是哪種異常?如果不會則打印結果是什么
// 這里可能會報一個越界ArrayIndexOutOfBoundsException
if (args[4].equals("john")) {
System.out.println("AA");
}else {
System.out.println("BB");
}
Object o = args[2]; // 這里的編譯類型是Object,這里的運行類型是String,當前指向String
Integer i = (Integer)o; // 按理來說應該要轉換成為String,但是這里轉換成為Integer,Integer和String沒有什么關系,出現
// ClassCastException
*/
/*
寫出程序結果
B
C
D
*/
//public class Homework07 {
// public static void func() {
// try {
// throw new RuntimeException(); // 拋出一個運行時異常RuntimeException
// } finally {
// System.out.println("B"); // finally這里還是要輸出
// }
// }
// public static void main(String[] args) {
// try {
// func(); // 運行時候異常默認丟到調用的地方
// System.out.println("A"); // 上面產生了異常,這行代碼不會再執行
// }catch(Exception e) {
// System.out.println("C"); // 捕獲運行時異常,輸出C
// }
// System.out.println("D"); // 異常得到捕獲,所以程序不會結束,正常輸出
// }
//}
/*
寫出程序結果
B
C
D
*/
public class Homework07 {
public static void main(String[] args) {
try {
showExce(); // 接收到拋出的異常,這里進行捕獲
System.out.println("A"); // 后面的這個代碼不會被執行
} catch (Exception e) {
System.out.println("B"); // 捕獲到Exception異常進行處理
} finally {
System.out.println("C"); // 不管是否有異常都要執行
}
System.out.println("D"); // 因為捕獲了異常所以程序不會結束,這條語句被輸出
}
public static void showExce() throws Exception { // 因為Exception是編譯時異常,需要手動拋出
throw new Exception();
}
}
六、包裝類
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useclass01 {
public static void main(String[] args) {
}
}
/*
常用類
這個章節涉及到的內容
包裝類
String
StringBuffer
StringBuilder
Math
Date,Calendar,LocalDate...
System
Arrays
BigInteger BigDecimal
一、包裝類Wrapper
1、針對八種基本數據類型相應的引用類型-包裝類
2、因為有了類,就可以調用類中的方法。
基本數據類型:boolean char byte short int long float double
包裝類: Boolean Character Byte Short Integer Long Float Double
其中:Byte Short Integer Long Float Double 的父類是Number
先來看看Boolean的類圖
再來看Character
Byte
因為后面這幾個的父類也是Number的,就可以寫在一起
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass02 {
public static void main(String[] args) {
// 1手動裝箱
// Integer的裝箱
// JDK5以前是手動裝箱和拆箱
// 手動裝箱,基本數據類型得到包裝類型
int n1 = 100;
Integer integer = new Integer(n1); // 第一種方式
Integer integer1 = Integer.valueOf(n1); // 第二種方式
// 2手動拆箱
// 將包裝類型得到普通類型
int i = integer.intValue();
// JDK5以及以后
// 就可以自動裝箱和自動拆箱了
int n2 = 200;
// 自動裝箱
Integer integer2 = n2; // 將基本數據類型直接賦給包裝類型
// 底層使用的仍然是Integer.valueOf(n1);
// 自動拆箱同樣是直接賦值
int n3 = integer2; // 實際上底層仍然使用的還是這里的intValue()
// 其他包裝類的用法類似,這里就不一一的舉例
}
}
/*
包裝類和基本數據類的轉換
包裝類
包裝類和基本數據類型的轉換
演示包裝類 和 基本數據類型的相互轉換,這里以int和Integer演示。
1、JDK5以前的手動裝箱和拆箱的方式,裝箱:基本類型->包裝類型
反之,拆箱
2、JDK5以后含有JDK5的自動裝箱和拆箱方式
3、自動裝箱底層調用的是valueOf方法,比如Integer.valueOf()
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass03 {
}
/*
包裝類的課堂測試題
下面代碼是否正確
Double d = 100d; // 自動裝箱,底層使用Double.valueOf(100d);
Float f = 1.5f; // 自動裝箱, 底層使用Float.valueOf(1.5f);
如下兩個題目輸出結果是相同的嗎,各是什么?
Object obj1 = true?new Integer(1):new Double(2.0);
System.out.println(obj1); //1.0,因為前面三元運算符中精度最高的部分是double,所以精度會提升到double
// 也就是三元運算符要看作一個整體。
Object obj2;
if(true) obj2 = new Integer(1);
else obj2 = new Double(2.0);
System.out.println(obj2); // 1,這里和三元運算符不一樣,是分開來運算的。
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass04 {
public static void main(String[] args) {
// 包裝類Integer->String
Integer i = 100; //自動裝箱 int -> Integer
// 方式1
String str1 = i + ""; // i還是Integer沒有變,只是產生了一個新的對象給str1,Integer->String
// 方式2
String str2 = i.toString();
// 方式3
String str3 = String.valueOf(i);
// 將String轉換成包裝類
String str4 = "12345";
Integer i2 = Integer.parseInt(str4); // 這邊其實返回的是一個int類型,但是因為有自動裝箱還可以轉為Integer
// 方式二可以使用構造器
Integer i3 = new Integer(str4); // 構造器f
// 常用的方法
System.out.println(Integer.MIN_VALUE); // 返回類型支持的最小值
System.out.println(Integer.MAX_VALUE); // 返回類型支持的最大值
System.out.println(Character.isDigit('a')); // 判斷是不是數字
System.out.println(Character.isLetter('a')); // 判斷是不是字母
System.out.println(Character.isUpperCase('a')); // 判斷是不是大寫
System.out.println(Character.isLowerCase('a')); // 判斷是不是小寫
System.out.println(Character.isWhitespace('a')); // 判斷是不是空格
System.out.println(Character.toUpperCase('a')); // 轉成大寫
System.out.println(Character.toLowerCase('A')); // 轉小寫
}
}
/*
包裝類型和String類型的相互轉換WrapperVSString.java
*/
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
/*
看一道面試題,輸出的什么結果,為什么
*/
public class useClass05 {
public static void main(String[] args) {
new AA().method1();
}
}
class AA {
public void method1() {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); // 判斷對象,兩個對象使用==判斷對象是不是同一個false
Integer m = 1; // 底層使用Integer.valueOf(1);
Integer n = 1; // 在-128到127就是直接返回,不會new,所以是true
System.out.println(m == n); // 看看底層代碼是怎么寫的,不能判斷是不是new出來的,這里為true
// 也可以看源碼中的IntegerCache.cache這個數組,其實已經創建好了。
Integer x = 128; // 128了不再范圍中,需要new,所以這里為false
Integer y = 128;
System.out.println(x == y);
/*
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
取決i是多少,這個范圍是關鍵,
可以看源碼中的注釋
“This method will always cache values in the range -128 to 127,”
或者繼續追low和high就能看到了。
*/
}
}
package com.exercise.trycatch.useclass;
/**
* @author alice_huijing
* @version 1.0
*/
public class useClass06 {
public static void main(String[] args) {
/*
public Integer(int value) {
this.value = value;
}
*/
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2); //通過new的方式創建對象,不是同一個對象,false
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4); // false
/*
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
-128 to 127
*/
Integer i5 = 127;
Integer i6 = 127;
System.out.println(i5 == i6); // 不是通過new的方式,所以是同一個對象
Integer i7 = 128;
Integer i8 = 128;
System.out.println(i7 == i8); // 超過了了127了,所以通過的是new創建對象,所以不是同一個對象。
Integer i9 = 127;
Integer i10 = new Integer(127); // 使用了new
System.out.println(i9 == i10);
Integer i11 = 127;
int i12 = 127;
System.out.println(i11 == i12); // 只要有一個是基本數據類型就是判斷的值是否相等。
Integer i13 = 128;
int i14 = 128;
System.out.println(i13 == i14); // 只要有一個是基本數據類型就判斷的值是否相等。
}
}
/*
Integer類的面試題總結
看看下面代碼,輸出什么結果。
*/
七、附圖
![image]()