乐趣区

关于java:Java异常机制

前言

申明: 该文章中所有测试都是在 JDK1.8 的环境下。

该文章是我在学习 Java 中的异样解决这方面常识时,做的一些总结和记录。

如果有不正确的中央请大家多多包涵并作出指导,谢谢!

一、异样机制介绍

1.1 基本概念

什么是异样?顾名思义就是非正常的景象。就是 Java 程序在运行的时候呈现不失常的状况。举个例子:咱们有一个等式 ”10/0=?” 须要计算,咱们都晓得,10 除以 0 后果是无意义的,所以咱们用 Java 程序计算该等式就会呈现非正常景象。

1.2 异样类体系

在理解了异样的概念之后,那么接下来须要晓得 Java 中异样是如何示意的。

首先须要意识 java.lang.Throwable 类,这个类是 Java 中所有谬误(Error)和异样(Exception)的超类。

  • 谬误(Error):个别是 Java 虚拟机相干的,无奈解决的严重错误。例如零碎解体,虚拟机谬误。
  • 异样(Exception):次要是一些编程谬误,能够通过编写代码解决。比方下面讲的计算 0 作为除数的等式。

所以,咱们重点须要学习的是可能通过编写代码解决问题的 ” 异样(Exception)”。

1.3 异样的品种

java.lang.Exception 这是所有异样的超类。而后咱们查看 java.lang.Exception 类,发现该异样类上面有好多子类。那这么多异样类,该如何辨别和记忆呢?

咱们依据程序异样在编译期间是否被检测进去,把异样分为两种:

  • RuntimeException:运行时异样,也叫非检测性异样。
  • 其余异样:非运行时异样,也叫检测性异样。

上面给非检测性异样和检测性异样举例:

public class Test {public static void main(String[] args) {

        //1. 非检测性异样
        System.out.println(10 / 0); // 编译胜利,程序能够间接运行,然而在运行代码时会产生算术异样(java.lang.ArithmeticException)//2. 检测性异样
        FileInputStream file = new FileInputStream("d:/a.txt"); // 编译时间接谬误, 程序不能间接运行
    }
}

RuntimeException 的次要子类:

  1. ArithmeticException:算术异样
  2. ArrayIndexOutOfBoundsException:数组下标越界异样
  3. NullPointerException:空指针异样
  4. IllegalArgumentException:不非法参数异样
  5. ClassCastException:类型转换异样
  6. NumberFormatException:数字格局异样

1.4 异样类构造体系图

依据下面列出的异样品种,能够形成以下的异样类构造体系图:

二、异样解决

开始前须要先明确为什么须要异样解决?

程序中出现异常,并且没对其进行解决,会导致程序的中断执行,一旦产生异样,异样之后的语句并不会被执行,而是间接完结程序。

2.1 异样的防止

能够用 if 条件判断语句进行运行时异样的防止,咱们就依据下面最常见的几个子类举例子。

首选咱们碰到如下三种异样:

public class ExceptionAvoid {public static void main(String[] args) {

        // 呈现算术异样
        int a = 10;
        int b = 0;
        System.out.println(a / b);

        // 呈现数组下标越界异样
        int[] arr = new int[3];
        int c = 3;
        System.out.println(arr);

        // 呈现空指针异样
        String str = null;
        System.out.println(str.length());

    }
}

应用 if 条件判断语句进行异样防止:

public class ExceptionAvoid {public static void main(String[] args) {
        
        int a = 10;
        int b = 0;
        // 防止算术异样
        if (0 != b) {System.out.println(a / b);
        }
        
        int[] arr = new int[3];
        int c = 3;
        // 防止数组下标越界异样
        if (c >= 0 && c < 3) {System.out.println(arr);
        }
        
        String str = null;
        // 防止空指针异样
        if (null != str) {System.out.println(str.length());
        }

    }
}

缺点: 尽管 if 条件判断语句能够很好的进行异样防止,然而过多会导致代码加长,可读性差。

2.2 异样的捕捉

概念: 对程序中可能呈现的异样进行捕捉解决,如果程序产生异样,则会被捕捉,进行一些自定义操作。

语法格局:

try {可能产生异样的代码} catch (异样类型 援用变量名) {出现异常后进行解决的代码} finally {无论是否产生异样都要执行的代码}

注:catch 代码块能够有多个,finally 代码块能够没有 

不想应用 if 条件判断语句进行异样防止,或者该异样是非运行时异样,能够进行异样的捕捉解决,如下所示。

public class ExceptionCatch {public static void main(String[] args) {

        // 运行时异样
        int a = 10;
        int b = 0;
        try {System.out.println(a / b);
        } catch (ArithmeticException e) {System.out.println("呈现算术异样");
        } 

        // 非运行时异样
        try {FileInputStream fis = new FileInputStream("d:/a.txt");
        } catch (FileNotFoundException e) {System.out.println("呈现文件未找到异样");
        } finally {System.out.println("该代码肯定被执行");
        }
    }
}

流程剖析:

1、如果在 try 代码块中没有异样,则程序不会进入 catch 代码块,而是把 try 代码块中的程序走完,例子如下:

public class ExceptionCatch {public static void main(String[] args) {

        int a = 10;
        int b = 2;
        try {System.out.println("1");
            System.out.println(a / b);
            System.out.println("2");
        } catch (ArithmeticException e) {System.out.println("3");
        }
        
    }
}

则输入后果:
1
2
5

2、如果在 try 代码块中的某一行代码出现异常,则程序不会在 try 代码块中继续执行,而是间接进入 catch 代码块,并把 catch 代码块的程序走完,例子如下:

public class ExceptionCatch {public static void main(String[] args) {

        int a = 10;
        int b = 0;
        try {System.out.println("1");
            System.out.println(a / b);
            System.out.println("2");
        } catch (ArithmeticException e) {System.out.println("3");
        }
        
    }
}

则输入后果:1
3

3、无论异样是否呈现并被捕捉,finally 代码块中代码肯定会执行,例子如下:

public class ExceptionCatch {public static void main(String[] args) {

        int a = 10;
        int b = ?;
        try {System.out.println("1");
            System.out.println(a / b);
            System.out.println("2");
        } catch (ArithmeticException e) {System.out.println("3");
        } finally {System.out.println("4");
        }

    }
}

如果 b = 0;则输入后果:1
3
4
如果 b = 2;则输入后果:1
2
4

4、如果有异样呈现并被捕捉,则程序不会被终止,例子如下:

public class ExceptionCatch {public static void main(String[] args) {

        int a = 10;
        int b = 0;
        try {System.out.println("1");
            System.out.println(a / b);
            System.out.println("2");
        } catch (ArithmeticException e) {System.out.println("3");
        } finally {System.out.println("4");
        }
        
        System.out.println("5");
    }
}

则输入后果:1
3
4
5

提出问题: 代码中存在多个异样的可能,那该如何解决?

解决办法: 应用多个 catch 代码块捕捉可能呈现的异样,最初一个 catch 代码块中应用 Exception 兜底。

public class ExceptionCatch {public static void main(String[] args) {

        try {div(4,0);
        } catch (ArithmeticException e) {System.out.println("呈现算术异样");
        } catch (ArrayIndexOutOfBoundsException e) {System.out.println("呈现斧正越界异样");
        } catch (Exception e) {System.out.println("出现异常");
        }
    }

    public static int div(int a, int b) {int []arr = new int [a];
        System.out.println(arr[4]);// 制作的第一处异样
        return a/b;// 制作的第二处异样
    }
}

注:在存在多个 catch 代码块的程序中,父类异样不能放在子类异样后面,例如:Exception 不能放在 ArithmeticException 之前。


注:在存在多个 catch 代码块的程序中,父类异样不能放在子类异样后面,例如:Exception 不能放在 ArithmeticException 之前。

2.3 异样的抛出

概念:

在某些非凡的状况下有些异样不能解决或者不便解决,就能够将该异样转移给该办法的调用者。当办法执行出现异常,则底层生成一个对象类抛出,此时异样代码后续的代码就不会再执行。

语法格局:

拜访权限 返回值类型 办法名称(参数列表)throws 异样类型 1,异样类型 2 ….{办法体;}

public void test(int a) throws Exception {}

示例代码:

public class ExceptionThrow {public static void main(String[] args) {
        try {show();
        } catch (IOException e) {e.printStackTrace();
        }
    }

    public static void show() throws IOException {FileInputStream fileInputStream = new FileInputStream("d:/a.txt");
        fileInputStream.close();}
}

依据示例代码,阐明三个问题:

  1. 有时候为了集中处理异样,咱们能够在存在异样的办法中进行异样抛出,到最初进行集中异样解决。而异样捕捉只能在该办法中间接解决。
  2. 主办法中进行异样捕捉而不是异样抛出是因为主办法再往上抛异样就把异样抛给了 JVM,不利于异样解决。
  3. show 办法中的异样底层起源:

    ①首先进入 FileInputStream 类中,能够看到该构造方法中创立了 File 的实例。

    ②进入 File 类中,能够看到底层抛出的异样。

办法重写后抛出异样的注意事项:

  • 子类不容许抛出的异样

    • 比父类更大的异样
    • 和父类平级然而不一样的异样
  • 子类容许抛出的异样

    • 能抛出一样的异样
    • 能抛出更小的异样
  • 子类能够不抛出异样

2.4 自定义异样

概念:

当程序须要表白年龄不合理时,java 官网又没提供这个针对性的异样,此时程序员须要自定义异样加以形容。

自定义异样实现:

创立一个自定义异样类继承 Exception 类或其子类

public class AgeException extends Exception {public AgeException() { }

    public AgeException(String message) {super(message);
    }
}

自定义异样类应用:

创立一个 Person 类,在 setAge 办法中抛出自定义异样。

public class Person {

    private String name;

    private int age;
    
    public Person() {}

    public Person(String name, int age) throws AgeException {setName(name);
        setAge(age);
    }

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public int getAge() {return age;}

    public void setAge(int age) throws AgeException {if (age > 0 && age < 200) {this.age = age;} else {throw new AgeException("年龄不合理哦")
        }
    }
}

执行主办法查看后果:

public class Test {public static void main(String[] args) {

        try {Person person = new Person("Bob",210);
        } catch (AgeException e) {e.printStackTrace();
        }
    }
}

输入后果为:AgeException: 年龄不合理哦
at Person.setAge(Person.java:36)
at Person.<init>(Person.java:17)
at Test.main(Test.java:13)

三、总结

一个异样类构造体系图

三个异样解决办法

一个自定义异样

退出移动版