Java的异常机制(概念)

Java语言中的异常处理包括的四个环节。

  • 声明异常
    throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异常对象。
  • 抛出异常
    throw用于抛出异常。
  • 捕获异常
    try是用于检测被包住的语句块是否出现异常,如果有异常,则抛出异常,并执行catch语句。
  • 处理异常
    cacth用于捕获从try中抛出的异常并作出处理。
    finally语句块是不管有没有出现异常都要执行的内容。

简述Java中的异常处理机制的简单原理和应用。

异常是指java程序运行时(非编译)所发生的非正常情况或错误, Java使用面向对象的方式来处理异常, 它把程序中发生的每个异常也都分别封装到一个对象来表示,该对象中包含有异常的信息。

虚拟机必须宕机的错误属于error,程序可以死掉也可以不死掉的错误属于系统异常,程序不应该死掉的错误属于普通异常;

Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,下面又派生了两个子类:Error和Exception;

Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了, 例如,说内存溢出和线程死锁等系统问题。

Exception表示程序还能够克服和恢复的问题,其中又分为系统异常(运行时异常,非检查)和普通异常(检查);
系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);

普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,IO异常,以及SQL异常发生这样的异常后,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,checked 异常也就是我们经常遇到的IO异常,以及SQL异常都是这种异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch。因为普通异常和运行环境有关系,具客观性,不可决定性和不可预测性!必须捕获或者抛给上层。而系统异常(也叫rutime exception)可以处理也可以不处理,所以编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常

error和exception有什么区别?

Error指程序本身不能恢复和克服的一种严重问题。比如说内存溢出,线程死锁。不可能指望程序能处理这样的情况。

Exception指软件本身设计的问题(系统异常也叫运行时,使用者无法克服)或运行环境变化导致的问题(普通异常也叫检查异常,使用者可以克服),程序本身能恢复和克服。也就是说它表示如果程序运行正常,从不会发生的情况。

运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常(也叫非检查异常)表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。javac要求方法必须声明,抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

异常相关问题

try-finally中return问题

public class TryReturn1 {
    public static void main(String[] args) {
        System.out.println(get());
    }
    public static int get() {
        try {
            return 1;
        } finally {
            return 2;
        }
    }
}

输出:2
分析:
在一个try-finally 语句中,finally 语句块总是在控制权离开try 语句块时执行的,但是finally中如果有return则try中的return结果不再返回给主调者。
即,如果finally里也有返回语句,那么以finally的为主。也就是说,千万不要用一个return、break、continue 或throw 来退出一个finally 语句块,且千万不要允许将一个受检查的异常传播到一个finally 语句块之外去。容易出一些潜在bug。

public class TryReturn2 {
    public static void main(String[] args) {
        System.out.println(get());
    }
    public static int get() {
        int x = 1;
        try {
            return x;
        } finally {
            ++x;
        }
    }
}

输出:1
分析:
执行try时,遇到return语句,且还有finally语句块,那么程序此时一定要到finally执行,但是在转去finally语句块之前,try中先把要返回的结果(虽然准备好了返回值,但是还没返回呢,所以我说是执行的中间)存放到不同于X的局部变量中,执行完finally后,在从局部变量中取出原返回结果,因此,即使finally中对变量x进行了改变,但是不会影响返回结果。因为方法内使用栈保存返回值。

try-finally-exit问题

public class TryExit {
    public static void main(String[] args) {
        try {
            System.out.println("Hello world");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("Goodbye world");
        }
    }
}

输出:Hello world
分析:System.exit 将立即停止所有的线程,它并不会使finally 语句块得到调用,但是它在停止VM 之前会执行关闭挂钩操作。当VM 被关闭时,请使用关闭挂钩来终止外部资源。通过调用System.halt 可以在不执行关闭挂钩的情况下停止VM,但是这个方法很少使用。

try-catch问题

 public static void foo() {
        try {
            System.out.println("Hello,World!");
        } catch (IOException e) {
            System.out.println("Exception!");
        }
    }

这段代码编译通不过,因为println()并不抛出异常。Java语言规范中描述道:如果一个catch 子句要捕获一个类型为 E 的被检查异常,而其相对应的try 子句如不能抛出E 的某种子类型的异常,那么这就是一个编译期错误。

 public static void bar() {
        try {
        } catch (Exception e) {
            System.out.println("Exception!");
        }
    }

这段代码编译可以编译通过,并且输出:Exception!
分析:catch 子句检查了Exception,捕获 Exception 或 Throwble 的 catch 子句是合法的,不管与其相对应的 try 子句的内容为何。

总结

关于Java异常这一方面暂时就总结这些内容了,如果有好问题会继续补充的。

注:本文转载自Core Java 经典笔试题总结(异常类问题)


本文转载:CSDN博客