Java 异常的学习

了解异常

常见的几种异常

除以0 (算数异常)

System.out.println(10/0);
//执行结果
Exception in thread "main" java.lang.ArithmeticException: / by zero

数组越界异常

 int[] array = {1,2,3,5,6};
 System.out.println(array[10]);
 // 执行结果
 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10

空指针异常

 public static void main(String[] args) {
        int[] array = null;
         System.out.println(array[1]);
 }        
 // 执行结果
 Exception in thread "main" java.lang.NullPointerException

防御式编程

LBYL :
在操作之前就做好充分检查。

EAFP

先操作,遇到问题再处理。

EAFP风格的代码:
try {

}catch{

}

Java中异常的核心思想就是 EAFP

异常分类

运行时异常(非受查异常)

程序运行期间发生的错误,运行异常。

指程序已经编译通过得到了class文件,再由JVM执行过程中出现的错误。

public static void main(String[] args) {
        int a = 10;
        int b = 0;
        System.out.println(a/b);// 出现算术异常
     //  java.lang.ArithmeticException: / by zero
        System.out.println("lalal"); //此程序不会执行
    }

a / b = 10 / 0,这个异常会交给JVM来处理,一旦交给JVM,那么程序就会异常终止。

编译时异常(受查异常)

程序编译期间异常。
在这里插入图片描述

异常的基本用法

▷捕获异常

try catch 的使用

1. try catch 基本语法

 try {
        可能会发生的异常;
 }catch(异常类型 异常对象){
        处理异常;
 }finally {
        异常的出口;
    }

✪ try代码块 中放的是可能会出现异常的代码。
✪ catch代码块 中放的是出现异常后的处理行为。
✪ finally代码块中的代码用于处理善后工作,会在最后执行。
✪ catch 和 finally 都可以根据情况选择加或不加。

2. 使用try catch 处理异常

 int a = 10;
 int b = 0;
 try {
    System.out.println(a/b);// 出现异常
    System.out.println("哈哈"); //此程序不会继续执行
}catch (ArithmeticException e ) {  
       e.printStackTrace();
       System.out.println("捕获了空指针异常");
}

// 执行结果
java.lang.ArithmeticException: / by zero
	at demo1.Test0.main(Test0.java:21)
捕获了空指针异常

❈ 一旦 try 中出现异常,那么 try 代码块中的程序不会继续执行,而是交给catch 中的代码来执行。catch 执行完毕会继续向下执行。

3. catch 只能处理对应种类的异常

 try {
      int a = 10;
      int b = 10;
      System.out.println(a/b);
      System.out.println("哈哈");
      String str = null;
      System.out.println(str.length());// 代码会抛出空指针异常
}catch (ArithmeticException e ) {  
      e.printStackTrace();
      System.out.println("捕获了算数异常");
}

// 执行结果
1
哈哈
Exception in thread "main" java.lang.NullPointerException
	at demo1.TestDemo.main(TestDemo.java:44)

因为异常类型不匹配,所以 catch 语句不能捕获空指针异常。

4. catch可以有多个

 try {
      int a = 10;
      int b = 10;
      System.out.println(a/b);
      String str = null;
      System.out.println(str.length());
}catch (ArithmeticException e ) { 
         e.printStackTrace();
         System.out.println("捕获了算数异常");
}catch (NullPointerException e){
         e.printStackTrace();
         System.out.println("空指针异常");
}

// 执行结果
1
空指针异常
java.lang.NullPointerException
	at demo1.TestDemo.main(TestDemo.java:44)

如果多个异常的处理方式是相同的,也可以写成如下形式:

catch (ArithmeticException e | NullPointerException e) { 
         e.printStackTrace();     
}

5. 也可以用一个 catch 捕获所有异常

try {
     int a = 10;
     int b = 10;
     System.out.println(a/b);
     String str = null;
     System.out.println(str.length());
}catch (Exception e ) {  
        e.printStackTrace();
        System.out.println("捕获了算数异常或空指针异常");
}
     System.out.println("lalal");
     
// 执行结果
1
捕获了算数异常或空指针异常
lalal
java.lang.NullPointerException

Exception 类是所有异常类的父类,所有可以用这个类型表示所有异常。
catch 在进行类型匹配的时候,不光会匹配相同类型的异常对象,也会捕捉目标异常类型的子类对象。
ArithmeticException 和 NullPointerException 都是Exception 的子类,因此都会被捕捉。

♦ 写catch 时 (父类与子类一同出现时父类异常不要放到最前面 , 不然后面其他子异常捕获不到,会报错。如下图:
一般不太推荐使用Exception
在这里插入图片描述
Exception的使用 示例:

public void getCustomerInfo() {
    try {
      // do something that may cause an Exception
    } catch (java.io.FileNotFoundException ex) {
      System.out.print("FileNotFoundException!");
    } catch (java.io.IOException ex) {
      System.out.print("IOException!");
    } catch (java.lang.Exception ex) {
      System.out.print("Exception!");
    }
  }

有如下四种结果,想一想程序最终的运行结果是什么?
在这里插入图片描述
程序运行出现异常时,catch 只会捕获一处异常
正确答案:A

6. 如果本方法中没有合适的处理异常的方式,就会沿着调用栈向上传递

 public static void function(){
        System.out.println(10/0);
    }
    public static void main(String[] args) {
     function();
    }

function 没有处理异常 就会给 main 处理异常,
main 函数没有处理异常,就只能交给 JVM 处理,
交给 JVM 处理,程序会异常终止。所以如下:

✍✍ 一定要自己处理异常

 public static void function(){
        System.out.println(10/0);
    }
    public static void main(String[] args) {
     try {
         function();
     }catch (ArithmeticException e){
         e.printStackTrace();
     }
      System.out.println("结束");
    }
// 执行结果
java.lang.ArithmeticException: / by zero
	at demo1.TestDemo.function(TestDemo.java:29)
	at demo1.TestDemo.main(TestDemo.java:33)
结束

7. 如果向上传递一直没有合适的方法处理异常,最终会交给 JVM 处理,程序就会异常终止。

 public static void func2(){
        System.out.println(10/0);
    }
    public static void main(String[] args) {
        func2();
        System.out.println("结束");
    }

// 执行结果
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at demo1.TestDemo.func2(TestDemo.java:22)
	at demo1.TestDemo.main(TestDemo.java:25)

程序没有执行 System.out.println(“结束”);
显然,程序终止异常了。

finally 语句

在异常处理中,完成释放资源关闭数据库关闭文件等工作。

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            String str1 = scanner.nextLine();
            System.out.println(str1);
        }catch (NullPointerException e){
            e.printStackTrace();
        }finally {
            scanner.close();
        }
    }

scanner 可以看作一种资源,输入之后再关闭。

▶▷上述代码进行优化
鼠标放在 try 上 ,Alt + Enter >> Replace
若使用 try( 某个资源 ),
后面就可不再使用 finally。

 public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            String str1 = scanner.nextLine();
            System.out.println(str1);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

Scanner 对象在try( ) 中创建,就能保证在 try 执行完毕后自动调用 Scanner 的 close 方法。

finally 的注意事项
public static int func() {
        try {
            int a = 20;
            return a;
        }catch (NullPointerException e) {
            System.out.println("空指针异常!");
        }finally {                        
            return 30; // 以后不要在finally 中写return
        }  
    }
    public static void main(String[] args) {
        System.out.println(func());
    }
    //执行结果
    30

注意:
执行 finally 一般在方法返回之前(try 或者 catch 中 如果有 return 会在这个return 之前执行 finally),但如果 finally 中也存在 return 语句 ,那么就会执行 finally 中的 return,不会执行 try 中的 return。

尽量不要在 finally 中写 return

▷处理异常流程

  1. 先执行 try 语句;
  2. 如果 try 中代码出现异常,则结束 try 中代码,查看 catch 中捕获异常是否匹配;
  3. 若找到匹配的异常类型,就执行 catch 中的代码;
  4. 若没有找到匹配的异常类型,就将异常向上传递到上层调用者;
  5. 无论是否找到匹配的异常类型,finally 中的代码都会被执行到(在该方法结束前执行);
  6. 如果上层调用者也没有处理异常,则继续向上传递;
  7. 直到 main 方法也没有合适的代码处理异常,就会交给 JVM 处理,此时程序就会异常终止。

▷抛出异常

  1. throw 手动抛出异常
public static void func0(int a,int b){
        if (b == 0){
            throw new ArithmeticException("除0异常");
        }
        System.out.println(a/b);
    }
    public static void main(String[] args) {
        try {
            func0(10, 0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
        System.out.println("lalal");
    }

抛出异常后,要再进行手动捕获异常

  1. 声明异常 throws
 public static void func0(int a,int b) throws ArithmeticException{
        if (b == 0){
            throw new ArithmeticException("除0异常");
        }
        System.out.println(a/b);
    }
    public static void main(String[] args) {
        try {
            func0(10, 0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }

把可能抛出的异常标注在方法定义的位置上,提醒调用者要注意捕获这些异常。

▷自定义异常类

class MyException extends RuntimeException{
    public MyException(String message){
        super(message);
    }
}

class UserError extends Exception{
    public UserError(String message){
        super(message);
    }
}

在这里插入图片描述

注意 :
◈ 自定义异常通常会继承于 Exception 或者 RuntimeException;
◈ 继承于 Exception 的异常默认是受查异常;
◈ 继承于 RuntimeException 的异常默认是非受查异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值