目录
1.异常?
2.异常的基本用法
基本语法:
代码示例1: 不处理异常的情况
代码示例2: 使用 try catch 后的程序执行过程?
代码示例3: catch 可以有多个
代码示例4:?finally 表示最后的善后工作, 例如释放资源
代码示例5: finall 保证会执行到 Scanner 的 close 方法
代码示例6:使用 try 负责回收资源
代码示例7:如果本方法中没有合适的处理异常的方式, 就会沿着调用栈向上传递
代码示例8: 如果向上一直传递都没有合适的方法处理异常, 最终就会交给 JVM 处理, 程序就会异常终止(和我们最开始 未使用 try catch 时是一样的).?
代码示例9:尽量避免在finally当中写return
异常处理流程
抛出异常
3.Java 异常体系
显示处理的方法有两种:
① 使用 try catch 包裹起来
② 在方法上加上异常说明, 相当于将处理动作交给上级调用者
4.自定义异常类
例如: 实现一个简单的用户登录功能
练习1: 使用while循环建立类似" 恢复模型 " 的异常处理行为 , 它将不断重复, 直到异常不再抛出.
1.异常?
错误在代码中是客观存在的. 因此我们要让程序出现问题的时候及时通知程序猿.
我们有两种主要的方式
- LBYL: Look Before You Leap. 在操作之前就做充分的检查.
- EAFP: It's Easier to Ask Forgiveness than Permission. "事后获取原谅比事前获取许可更容易". 也就是先操作, 遇到 问题再处理.
异常的核心思想就是 EAFP.?
2.异常的基本用法
基本语法:
try{
???????? 有可能出现异常的语句 ;
} catch (异常类型 异常对象) {
} ... ?
[ finally {
异常的出口
} ]
- try 代码块中放的是可能出现异常的代码.
- catch 代码块中放的是出现异常后的处理行为.
- finally 代码块中的代码用于处理善后工作, 会在最后执行.
- ?finally 可以根据情况选择加或者不加.?
代码示例1: 不处理异常的情况
public static void main(String[] args) {
int[] nums = {1,2,3,4};
System.out.println("hehe");
System.out.println(nums[5]);
System.out.println("heihei");
}
?运行结果:
结论: 一旦发现了异常,程序就终止了,所以heihei不会被正常输出.
代码示例2: 使用 try catch 后的程序执行过程?
public static void main(String[] args) {
int[] nums = {1,2,3,4};
try {
System.out.println("hehe");
System.out.println(nums[5]);
System.out.println("heihei");
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();// 打印出现异常的调用栈
}
System.out.println("haha");
}
运行结果:
结论:我们发现, 一旦 try 中出现异常, 那么 try 代码块中的程序就不会继续执行, 而是交给 catch 中的代码来执行. catch执行完毕会继续往下执行?
代码示例3: catch 可以有多个
public static void main(String[] args) {
int[] nums = {1,2,3,4};
try {
nums = null;
System.out.println("hehe");
System.out.println(nums[5]);
System.out.println("heihei");
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();// 打印出现异常的调用栈
System.out.println("数组越界异常");
}catch (NullPointerException e){
e.printStackTrace();
System.out.println("空指针异常");
}
//(ArrayIndexOutOfBoundsException | NullPointerException e)
}
代码示例4:?finally 表示最后的善后工作, 例如释放资源
public static void main(String[] args) {
int[] nums = {1,2,3,4};
try {
nums = null;
System.out.println("hehe");
System.out.println(nums[5]);
System.out.println("heihei");
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();// 打印出现异常的调用栈
System.out.println("数组越界异常");
}catch (NullPointerException e){
e.printStackTrace();
System.out.println("空指针异常");
}finally {
System.out.println("finally");
}
}
运行结果:
结论:?无论是否存在异常, finally 中的代码一定都会执行到.
代码示例5: finall 保证会执行到 Scanner 的 close 方法
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
try{
int n = sc.nextInt();
System.out.println(10 / n);
}catch (InputMismatchException e){
e.printStackTrace();
System.out.println("输入错误");
}catch (ArithmeticException e){
e.printStackTrace();
System.out.println("算术异常,可能0作为了除数");
}finally {
sc.close();
System.out.println("finally执行了");
}
运行结果:
代码示例6:使用 try 负责回收资源
public static void main(String[] args) {
try(Scanner sc = new Scanner(System.in)){
int n = sc.nextInt();
System.out.println(10 / n);
}catch (InputMismatchException e){
e.printStackTrace();
System.out.println("输入错误");
}catch (ArithmeticException e){
e.printStackTrace();
System.out.println("算术异常,可能0作为了除数");
}finally {
System.out.println("finally执行了");
}
}
?运行结果:
代码示例7:如果本方法中没有合适的处理异常的方式, 就会沿着调用栈向上传递
public static void func(int n) {
System.out.println(10 / n);
}
public static void main(String[] args) {
try {
func(0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println("1234455");
}
?运行结果:
代码示例8: 如果向上一直传递都没有合适的方法处理异常, 最终就会交给 JVM 处理, 程序就会异常终止(和我们最开始 未使用 try catch 时是一样的).?
public static void func(int n) {
System.out.println(10 / n);
System.out.println("!23ggggg");
}
public static void main(String[] args) {
func(0);
System.out.println("!234");
}
运行结果:
代码示例9:尽量避免在finally当中写return
public static int func1() {
int a = 10;
try {
return a;
}catch (ArithmeticException e){
e.printStackTrace();
}finally {
return 20;
}
}
public static void main(String[] args) {
int a = func1();
System.out.println(a);
}
运行结果:
异常处理流程
- 程序先执行 try 中的代码
- 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
- 如果找到匹配的异常类型, 就会执行 catch 中的代码
- 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
- 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
- 如果上层调用者也没有处理的了异常, 就继续向上传递.
- 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.?
抛出异常
除了 Java 内置的类会抛出一些异常之外, 程序猿也可以手动抛出某个异常. 使用 throw 关键字完成这个操作.
public static int func2(int x) throws RuntimeException{
if(x==0){
throw new ArithmeticException("/ by 0");
}
return x/10;
}
public static void main(String[] args) {
int x = func2(0);
System.out.println(x);
}
3.Java 异常体系
- 顶层类Throwable派生出两个重要的子类,Error和Exception
- 其中Error指的是Java运行时内部错误和资源耗尽错误.应用程序不抛出此类异常.这种内部错误一旦出现,除了告知用户并使程序终止之外,再无能为力.这种情况很少出现.
- Exception是我们程序猿所使用的异常类的父类.
- 其中Exception有一个子类称为RuntimeException,这里面又派生出很多我们常见的异常类NullPointerException,IndexOutOfBoundsException等.
Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为 非受查异常, 所有的其他异常称为 受查异常.
如果一段代码可能抛出受查异常.那么必须显示进行处理.
如代码:
import java.io.File;
import java.util.Scanner;
public class Test2 {
public static String readFile(){
File file = new File("d:/test.txt");
Scanner sc = new Scanner(file);
return sc.nextLine();
}
public static void main(String[] args) {
System.out.println(readFile());
}
}
显示处理的方法有两种:
① 使用 try catch 包裹起来
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Test2 {
public static String readFile(){
File file = new File("d:/test.txt");
Scanner sc = null;
try {
sc = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return sc.nextLine();
}
public static void main(String[] args) {
System.out.println(readFile());
}
}
② 在方法上加上异常说明, 相当于将处理动作交给上级调用者
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Test2 {
public static String readFile() throws FileNotFoundException {
File file = new File("d:/test.txt");
Scanner sc = new Scanner(file);
return sc.nextLine();
}
public static void main(String[] args) throws FileNotFoundException {
System.out.println(readFile());
}
}
注 : 可以使用IDEA的alt + enter 快速修正代码.
4.自定义异常类
例如: 实现一个简单的用户登录功能
class NameError extends Exception{
public NameError(String message) {
super(message);
}
}
class PasswordError extends Exception{
public PasswordError(String message) {
super(message);
}
}
public class Test {
private static String name = "wangzhi";
private static String password = "123456";
public static void login(String name , String password) throws NameError, PasswordError {
if (!Test.name.equals(name)){
throw new NameError("用户名输入错误");
}
if (!Test.password.equals(password) ){
throw new PasswordError("密码输入错误");
}
System.out.println("登录成功!");
}
public static void main(String[] args) {
try {
login("wangzhi","12345");
} catch (NameError | PasswordError e) {
e.printStackTrace();
}
}
}
运行结果:
练习1: 使用while循环建立类似" 恢复模型 " 的异常处理行为 , 它将不断重复, 直到异常不再抛出.
public class TestDemo {
public static void main(String[] args) {
int i = 0;
while(i < 10){
try{
if(i<10) {
throw new Exception();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("第"+i+"次");
i++;
}
}
}
}
运行结果:
?
|