Java中的异常

欢迎关注我的公众号【软件大爆炸】
Java学习中的碎碎念
Java中易忽略的基础知识
Java面向对象基础
Java中的核心类
Java抽象类和接口
Java中的异常
Java中的泛型与集合
Java中的错误分三类:

  • 语法错误
  • 逻辑错误
  • 运行时错误

Java异常类之间的严格继承关系
Java中的异常_第1张图片
Java中的异常类主要分为两类:

  • 错误(Error)一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这些错误无法恢复或捕获,将导致应用程序中断。
  • 异常(Exception)因程序编码错误或外在因素导致的问题,这些问题能够被系统捕获并进行处理,从而避免应用程序非正常中断,例如,除以0、对负数开平方根、空指针访问等。

Throwable是所有异常类的父类, ErrorException都继承此类。当程序产生Error时,因系统无法捕获Error并处理,程序员将无能为力,程序只能中断;而当发生 Exception时,系统可以捕获并做出处理。

Exception异常从编程角度又可以分为以下两种类型:

  • 非检査型异常。编译器不要求强制处置的异常,该异常是因编码或设计不当导致的,这种异常可以避免, RuntimeException及其所有子类都属于非检查型异常
  • 检查型异常。编译器要求必须处理的异常,该异常是程序运行时因外界因素而导致的, Exception及其子类( RuntimeException及其子类除外)都属于检查型异常。
非检查型异常 类名 说明
ArrayIndexOutOfBoundsException 数组下标越界异常
NullPointerExpection 空指针访问异常
NumberFormatException 数字格式化异常
ArithmeticException 算术异常,比如除以零溢出
ClassCastException 类型转化不匹配异常
检查型异常 类名 说明
SQLException 数据库访问异常
IOException 文件操作异常
FileNotFoundException 文件不存在异常
ClassNotFoundException 类没有找到异常

程序员必须对检查型的异常进行处理,否则程序编译不通过,无法运行。

异常处理:为了使程序出现异常时也能正常运行下去,需要对异常进行相关的处理操作。

Java提供的异常处理机制有两种:

  • 使用try...catch捕获异常。将可能产生异常的代码放在try语句中进行隔离,如果遇到异常,程序会停止执行try块的代码,跳到 catch块中进行处理
  • 使用 throws声明抛出异常。当前方法不知道如何处理所出现的异常,该异常应由上一级调用者进行处理,可在定义该方法时使用 throws声明抛出异常。

关于try...catch

  • 执行try语句中的业务代码出现异常时,系统会自动生成一个异常对象,该异常对象被提交给Java运行时环境,此过程称为抛出异常.
  • 当Java运行时环境收到异常对象时,会寻找能处理该异常对象的 catch语句,即跟catch语句中的异常类型进行一一匹配,如果匹配成功,则执行相应的 catch块进行处理,这个过程称为捕获异常.

代码举例

  • 单catch处理语句:
public class ExceptionDemo1 {
    public static void main(String[] args) {
        try {
            int i = 1/0;
            System.out.println("i的值是"+i);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("代码结束!");
    }
}
java.lang.ArithmeticException: / by zero
	at club.BOOKJava8.ExceptionDemo1.main(ExceptionDemo1.java:6)
代码结束!

Process finished with exit code 0
名称 说明
getMessage() 返回该异常的详细描述字符串
printStackTrace() 将该异常的跟踪栈信息输出到标准错误输出
printStackTrace(PrintStream s) 将该异常的跟踪栈信息输出到指定输出流
getStactTrace() 方法返回该异常的跟踪栈信息
  • 多catch处理语句:
import java.util.Scanner;

public class ExceptionDemo1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[] array = new int[3];
        try {
            System.out.println("请输入第一个数");
            String str = scanner.next();
            int n1 = Integer.parseInt(str);

            System.out.println("请输入第二个数");
            int n2 = scanner.nextInt();

            array[1] = n1/n2;
            array[3] = n1 * n2;
            System.out.println("两个数字之和是:"+(n1+n2));
        }catch (NumberFormatException ex){
            System.out.println("数字格式化异常");
        }catch (ArithmeticException ex){
            System.out.println("算数异常");
        }catch (ArrayIndexOutOfBoundsException ex){
            System.out.println("下标越界异常");
        }catch (Exception ex){
            System.out.println("其他未知异常");
        }
        System.out.println("程序到此结束");
    }
}

第一组结果:

请输入第一个数
8
请输入第二个数
0
算数异常
程序到此结束

第二组结果:

请输入第一个数
8
请输入第二个数
6
下标越界异常
程序到此结束

捕获异常的顺序和 catch语句的顺序有关,因此安排 catch语句的顺序时,首先应该捕获一些子类异常,然后再捕获父类异常。

关于try...catch...finally
在某些时候,程序在try块中打开了一些物理资源,例如:数据库连接、网络连接以及磁盘文件读写等,针对这些物理资源,不管是否有异常发生,都必须显式回收;而在try块中旦发生异常,可能会跳过显示回收代码直接进入 catch块,导致没有正常回收资源。这种情况下就要求某些特定的代码必须被执行。在Java异常处理机制中,提供了 finally块,可以将回收代码放入此块中,不管try块中的代码是否出现异常,也不管哪一个 catch块被执行,甚至在try块或 catch块中执行了 return语句, finally块总会被执行。

注意:
Java垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存。在Java程序中,通常使用 finally回收物理资源。

代码示例

import java.io.FileInputStream;
import java.io.IOException;

public class Exception2 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try{
            fis = new FileInputStream("公众号软件大爆炸.txt");
        }catch (IOException ioe){
            System.out.println(ioe.getMessage());
            return ;
        }finally {
            if (fis != null){
                try{
                    fis.close();
                }catch (IOException ioe){
                    ioe.printStackTrace();
                }
            }
            System.out.println("执行finally块里的资源回收!");
        }
    }
}
公众号软件大爆炸.txt (系统找不到指定的文件。)
执行finally块里的资源回收!

从Java7开始,增强了try语句的功能,允许在try关键字后紧跟一对小括号,在小括号中可以声明、初始化一个或多个资源,当try语句执行结束时会自动关闭这些资源.

import java.io.FileInputStream;
import java.io.IOException;

public class AutoCloseDemo {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("软件大爆炸.txt")) {
            //do something to file
        }catch (IOException ioe){
            System.out.println(ioe.getMessage());
        }
    }
}
软件大爆炸.txt (系统找不到指定的文件。)

Process finished with exit code 0

抛出异常可以使用 throwthrows关键字

  • 使用 throw抛出一个异常对象:当程序出现异常时,系统会自动抛出异常,除此之外,Java也允许程序使用代码自行抛出异常,自行抛出异常使用 throw语句完成;
  • 使用 throws声明抛出一个异常序列:throws只能在定义方法时使用。当定义的方法不知道如何处理所出现的异常,而该异常应由上一级调用者进行处理,可在定义该方法时使用 throws声明抛出异常。

throw代码示例

import java.util.Scanner;

public class ThrowDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            System.out.println("请输入年龄:");
            int age = scanner.nextInt();
            if (age < 0 || age > 80){
                throw new Exception("请输入一个合法的年龄,年龄必须在0-80之间");
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
        System.out.println("程序结束了!");
    }
}
请输入年龄:
99
java.lang.Exception: 请输入一个合法的年龄,年龄必须在0-80之间
	at club.BOOKJava8.ThrowDemo.main(ThrowDemo.java:12)
程序结束了!

throws代码示例

import java.util.Scanner;

public class ThrowsDemo {
    public static void main(String[] args) {
        try {
            myThrowsFunction();
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void  myThrowsFunction() throws NumberFormatException, ArithmeticException, Exception{
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String str = scanner.next();
        int n1 = Integer.parseInt(str);
        System.out.println("请输入第二个数");
        int n2 = scanner.nextInt();
        System.out.println("您输入的两个数字相除为:" + (n1 / n2));
    }
}

请输入一个字符串
8
请输入第二个数
0
java.lang.ArithmeticException: / by zero
	at club.BOOKJava8.ThrowsDemo.myThrowsFunction(ThrowsDemo.java:25)
	at club.BOOKJava8.ThrowsDemo.main(ThrowsDemo.java:8)

Process finished with exit code 0

也可以使用自定义异常
自定义异常类都继承 ExceptionRuntimeException

import java.util.Scanner;

public class MyExceptionDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try{
            System.out.println("请输入年龄:");
            int age = scanner.nextInt();
            if (age < 0 || age > 80){
                throw new AgeException("年龄不合法,必须在0-80之间");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

class AgeException extends Exception{
    public AgeException(){
    }

    public AgeException(String msg){
        super(msg);
    }
}
请输入年龄:
88
club.BOOKJava8.AgeException: 年龄不合法,必须在0-80之间
	at club.BOOKJava8.MyExceptionDemo.main(MyExceptionDemo.java:12)

Process finished with exit code 0

你可能感兴趣的:(Java语言)