场景应用:列举常见的运行时异常 RuntimeException

常见的运行时异常

ClassCastException(类转换异常)

比如

Object obj=new Object(); 
String s=(String)obj;

IndexOutOfBoundsException(下标越界异常)
NullPointerException(空指针异常)
ArrayStoreException(数据存储异常,操作数组时类型不一致)
BufferOverflowException(IO 操作时出现的缓冲区上溢异常)
InputMismatchException(输入类型不匹配异常)
ArithmeticException(算术异常)

注意:运行时异常都是 RuntimeException 子类异常。

扩展:异常

Throwable 是 Exception 和 Error 的父类,Exception 虽然没有实现Serializable 接口,但是其父类 Throwable 已经实现了该接口,因此Exception 也支持 Serializable。

Throwable:Error 和 Exception

在这里插入图片描述

Error 类,表示仅靠程序本身无法恢复的严重错误,比如说内存溢出、动态链接异常、虚拟机错误。应用程序不应该抛出这种类型的对象。假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以在
进行程序设计时,应该更关注 Exception 类。

Exception 类,由 Java 应用程序抛出和处理的非严重错误,比如所需文件没有找到、零作除数,数组下标越界等。它的各种不同子类分别对应不同类型异常。可分为两类:Checked 异常和 Runtime 异常

Exception:运行时异常(Runtime )与受检异常(Checked )

异常表示程序运行过程中可能出现的非正常状态:

  • 运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。
  • 受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。

Java 编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。
异常和继承一样,是面向对象程序设计中经常被滥用的东西,神作《EffectiveJava》中对异常的使用给出了以下指导原则:

  • 不要将异常处理用于正常的控制流(设计良好的 API 不应该强迫它的调用者为了正常的控制流而使用异常)
  • 对可以恢复的情况使用受检异常,对编程错误使用运行时异常
  • 避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常发生)
  • 优先使用标准的异常
  • 每个方法抛出的异常都要有文档
  • 保持异常的原子性
  • 不要在 catch 中忽略掉捕获到的异常

面试题

类 ExampleA 继承 Exception,类 ExampleB 继承 ExampleA

有如下代码片断:

try{
    
    
	throw new ExampleB("b")
}catchExampleA e){
    
    
	System.out.println("ExampleA");
}catchException e){
    
    
	System.out.println("Exception");
}

请问执行此段代码的输出是什么?

答:输出:ExampleA。(根据里氏代换原则 [ 能使用父类型的地方一定能使用子类型 ],抓取 ExampleA 类型异常的 catch 块能够抓住 try 块中抛出的 ExampleB 类型的异常)

输出下面程序运行结果:

class Annoyance extends Exception {
    
    
}

class Sneeze extends Annoyance {
    
    
}

class Human {
    
    
    public static void main(String[] args) throws Exception {
    
    
        try {
    
    
            try {
    
    
                throw new Sneeze();
            } catch (Annoyance a) {
    
    
                System.out.println("Caught Annoyance");
                throw a;
            }
        } catch (Sneeze s) {
    
    
            System.out.println("Caught Sneeze");
            return;
        } finally {
    
    
            System.out.println("Hello World!");
        }
    }
}

输出:

Caught Annoyance
Caught Sneeze
Hello World!

分析,先执行内层try…catch块,能捕获到Sneeze异常,不再向外抛出、然后打印Caught Annoyance,第一层finally抛出Annoyance异常,根据里氏替换原则:能使用父类型的地方一定能使用子类型,这里也能替换为子类型异常,也能被捕获,然后打印Caught Sneeze,最终再在finally里打印Hello World!

猜你喜欢

转载自blog.csdn.net/weixin_45525272/article/details/127343692