异常

1、异常介绍

(1)基本概念

Java语言中,将程序执行中发生的不正常情况称为“异常”.(开发过程中的语法错误和逻辑错误不是异常)

快捷键: ctrl+alt+t,选中try-catch

执行过程中的异常可以分为两大类:

  1. Error(错误):Java虚拟机无法解决的严重问题。比如:JVM系统内部错误,资源耗尽等严重情况。比如:StackOverFlowErrorOOM(out of memory),Error是严重错误,程序会崩溃。
  2. Exception:其他因为编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等。Exception分为两类:运行时异常和编译时异常
(2)异常体系图

这里画了一些常见经典的异常。

Java异常和异常处理(主要是try-catch的掌握)-LMLPHP

总结:

  1. 异常分为两大类,运行时异常和编译时异常
  2. 运行时异常,编译器检查不出来,一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类以及它的子类都是运行时异常。
  3. 对于运行时异常,可以不做处理,因为这类异常很普遍,如果全部处理会对程序的可读性和运行效率产生影响。
  4. 编译时异常,是编译器要求必须处置的异常,不然编译不能通过,直接报错。

2、运行时异常

常见的运行时异常(RuntimeError)

  1. NullPointerException 空指针异常
  2. ArithmeticException 数字运算异常
  3. ArrayIndexOutOfBoundsException 数组下标越界异常
  4. ClassCastException 类型转换异常
  5. NumberFormatException 数字格式不正确异常

3、编译时异常

编译异常实在编译期间,就必须处理的异常,否则代码不能通过编译。

常见的编译异常有:

  1. SQLException 操作数据库,查询表可能发生异常
  2. IOException 操作文件时,发生的异常
  3. FileNotFoundException 当操作一个不存在的文件时,发生的异常
  4. EOFException 操作文件,到文件末尾,发生异常
  5. IllegalArguementException参数异常

4、异常处理

异常处理就是当异常发生事,对异常处理的方式

异常处理的方式:

  1. try-catch-finally 程序元在代码中捕获发生的异常,自行处理

    处理机制:

    try{
        代码/可能有异常
    }catch(Exception e){
        //捕获异常
        //1、当异常发生时
        //2、系统将异常封装成Exception对象e,传递给catch
        //3、得到异常对象后,程序员,自己处理
        //4、注意,如果没有发生异常,catch代码块不执行
    }finally{
        //1、不管try代码块是否有异常发生,始终要执行finally
        //2、所以,通常将释放资源的代码,放在finally
    }
    
  2. throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的就是JVM

    处理机制:

    Java异常和异常处理(主要是try-catch的掌握)-LMLPHP

(1)try-catch方式处理异常注意事项
  1. 如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch

  2. 如果异常没有发生,则会顺序执行try里面的代码块,不会进入到catch

  3. 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用finally

  4. 可以有多个catch,捕获不能的异常(进行不同的业务处理),要求父类异常在后面,子类异常前面(比如:Exception在后,NullPointerException在前,如果发生异常,只会匹配一个catch

    举例:

    public class TryCatchDetail01 {
        public static void main(String[] args) {
            //多个异常,可以多个catch,但是要求子类写在前面,父类写在后面
            try {
                Person person = new Person();
                System.out.println(person.getName());   //空指针异常
                int n1 = 10;
                int n2 = 0;
                int res = n1/n2;                    //算术异常
            } catch (NullPointerException e){
                System.out.println("空指针异常"+e.getMessage());
            }catch (ArithmeticException e){
                System.out.println("算术异常"+e.getMessage());
            }
            catch (Exception e) {
                System.out.println(e.getMessage());
            } finally {
            }
        }
    }
    
    class Person{
        private String name;
    
        public Person() {
        }
        public String getName() {
            return name;
        }
    }
    
  5. 可以进行try-finally配合使用,这种相当于没有捕获异常,程序会直接崩溃。应用场景,执行一段代码,不管是否发生异常,都会执行某个业务逻辑。

    try{
        //可能发生的语句
    }finally{
        //必须执行的
    }
    

5、throws处理异常

(1)基本介绍
  1. 如果一个方法(中的执行语句时)可能呢生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示的声明抛出异常,表明该方法不对这些异常进行处理,而是由该方法的调用者进行处理。
  2. 在方法声明中用throws语句可以什么抛出异常的列表,throw后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

举例:

//    public void f2() throws FileNotFoundException{
//    public void f2() throws FileNotFoundException, NullPointerException, ArithmeticException{
    public void f2() throws Exception{
        //抛出异常,让调用f2的调用者进行处理
        //throws后面可以是当前异常的父类,也可以抛出多个异常
        FileInputStream fis = new FileInputStream("d://aa.txt");
    }
}
(2)注意事项和使用细节
  1. 对于编译异常,必须进行处理
  2. 对于运行异常,程序没有运行,默认是throws处理
  3. 子类重写父类的方法是,对于抛出异常的规定:子类重写的方法,所抛出的异常要么和父类抛出的异常一致,要么是父类抛出异常的子类。
  4. throws的过程中,如果有方法try-catch,就相当于处理异常,可以不用throws

举例:

public class ThrowsDetails {
    public static void main(String[] args) {
        
    }
    public static void f1(){
        //运行时异常,会默认throws
        f2();
    }
    public static void f2() throws NullPointerException{  
    }
    
    public static void f3() throws Exception{
        //而编译类型的异常必须进行处理,否则会报错,调用者抛出的异常可以是之前的异常,或者之前的异常的父类
        f4();
    }
    public static void f4() throws FileNotFoundException {
    }
}

class A{
    public void f1() throws Exception{
    }
}

class B extends A{
    @Override
    //子类抛出的异常必须是父类的子类或者父类的异常
    public void f1() throws NullPointerException {
    }
}

6、自定义异常

(1)基本概念

当程序中出现了某些错误,但是该错误信息并没有在Throwable的子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。

(2)基本步骤
  1. 定义类,自定义异常类名,继承Exception或者RuntimeException
  2. 如果继承的是Exception,属于编译异常
  3. 如果继承的是RuntimeException,属于运行异常,一般来说都是继承RuntimeException

举例:

//自定义一个异常
//一般情况下,都是自定义为运行时异常,RuntimeException,这样可以使用默认的处理机制
class AgeException extends RuntimeException{
    public AgeException(String message) {//构造器
        super(message);
    }
}
(3) throws对比throw

举例:

public class CustomException {
    //throws
    public static void main(String[] args) throws Exception{
        int age = 180;
        if(!(age >= 18 && age <= 120)){
            //这里可以根据构造器,设置信息
            //throw
            throw new AgeException("年龄需要在18和120之间");
        }
        System.out.println("年龄范围正确");
    }
}
01-06 08:24