classcastexception异常_Java异常处理

异常

异常指不期而至的各种状况,异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。

比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error ;如果你用 System.out.println(11/0) ,那么你是因为你用0做了除数,会抛出 java.lang.ArithmeticException 的异常。

要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:

  • 检查性异常: 最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  • 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
  • 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

异常都是从 Throwable 类派生出来的,而 Throwable 类是直接从 Object 类继承而来。

异常发生的原因

  • 用户输入了非法数据。
  • 要打开的文件不存在
  • 网络通信时连接中断,或者JVM内存溢出

异常分类

9451a226b93af9fa6c3adcc0c0eae123.png
  • Error:系统内部错误,这类错误由系统进行处理,程序本身无需捕获处理。
  • Exception:可以处理的异常。
  • RuntimeException:可以捕获,也可以不捕获的异常。
  • 继承 Exception 的其他类:必须捕获,通常在 API 文档中会说明这些方法抛出哪些异常。

所有的异常类是从 java.lang.Exception 类继承的子类。而 Exception 异常下又主要分为两大类异常,一个是派生于 RuntimeExcption 的异常,一个是除了 RuntimeExcption 体系之外的其他异常。

RuntimeExcption 异常(运行时异常)通常有以下几种:

null

异常描述ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。ArrayIndexOutOfBoundsException用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。ArrayStoreException试图将错误类型的对象存储到一个对象数组时抛出的异常。ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常。IllegalArgumentException抛出的异常表明向方法传递了一个不合法或不正确的参数。IllegalMonitorStateException抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。IllegalStateException在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。IllegalThreadStateException线程没有处于请求操作所要求的适当状态时抛出的异常。IndexOutOfBoundsException指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。NegativeArraySizeException如果应用程序试图创建大小为负的数组,则抛出该异常。NullPointerException当应用程序试图在需要对象的地方使用 null 时,抛出该异常NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。SecurityException由安全管理器抛出的异常,指示存在安全侵犯。StringIndexOutOfBoundsException此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。UnsupportedOperationException当不支持请求的操作时,抛出该异常。

一般来说, RuntimeException 都是代码逻辑出现问题。

非 RuntimeException (受检异常,Checked Exception)一般有:

  • 打开一个不存在的文件
  • 没有找到具有指定名称的类
  • 操作文件异常

异常描述ClassNotFoundException应用程序试图加载类时,找不到相应的类,抛出该异常。CloneNotSupportedException当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。IllegalAccessException拒绝访问一个类的时候,抛出该异常。InstantiationException当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。InterruptedException一个线程被另一个线程中断,抛出该异常。NoSuchFieldException请求的变量不存在NoSuchMethodException请求的方法不存在

受检异常是编译器要求必须处理的异常,必须使用 try catch 处理,或者使用 throw 抛出,交给上层调用者处理。

异常的声明及抛出

throw抛出异常

当程序运行时数据出现错误或者我们不希望发生的情况出现的话,可以通过抛出异常来处理。

异常抛出语法:

throw new 异常类();//抛出异常    public static void fun1() {        Integer a = 1;        Integer b = null;        // 如果 a 或者 b 为 null 则抛出异常        if (a == null || b == null) {            throw new NullPointerException();        } else {            System.out.println(a+b);        }    }
throws声明异常

throws 用于声明异常,表示该方法可能会抛出的异常。如果声明的异常中包括 checked 异常(受检异常),那么调用者必须捕获处理该异常或者使用 throws 继续向上抛出。 throws 位于方法体前,多个异常之间使用 , 分割。

public static void main(String[] args) throws FileNotFoundException {        fun2();    }    //声明异常    public static void fun2() throws FileNotFoundException {        new FileInputStream("a.txt");    }
throw 和 throws的区别
  • throw 用于抛出异常对象,后面跟的是异常对象; throw 用在函数内。
  • throws 用于抛出异常类,后面跟的异常类名,可以跟多个,用逗号隔开。 throws 用在函数上

捕获异常

通常抛出异常后,还需要将异常捕获。使用 try 和 catch 语句块来捕获异常,有时候还会用到 finally 。

对于上述三个关键词所构成的语句块, try 语句块是必不可少的, catch 和 finally 语句块可以根据情况选择其一或者全选。你可以把可能发生错误或出现问题的语句放到 try 语句块中,将异常发生后要执行的语句放到 catch 语句块中,而 finally 语句块里面放置的语句,不管异常是否发生,它们都会被执行。

捕获异常对于系统而言,其开销非常大,所以应尽量减少该语句块中放置的语句。

public class Demo1 {    public static void main(String[] args) {        try{        //要检查的程序语句            System.out.println("I am try block.");            Class> tempClass = Class.forName("");            // 声明一个空的Class对象用于引发“类未发现异常”            System.out.println("Bye! Try block.");        }catch (ClassNotFoundException e) {        //异常发生时的处理语句            System.out.println("I am catch block.");            e.printStackTrace();            //printStackTrace()的意义在于在命令行打印异常信息在程序中出错的位置及原因            System.out.println("Goodbye! Catch block.");        }finally {        //一定会执行的语句            System.out.println("I am finally block.");        }    }}
注意下面事项
  • catch 不能独立于 try 存在。
  • 在 try/catch 后面添加 finally 块并非强制性要求的。
  • try 代码后不能既没 catch 块也没 finally 块。
  • try, catch, finally 块之间不能添加任何代码。
  • finally 很有用,主要用户关闭资源。无论是否发生异常,资源都必须进行关闭
捕获多个异常

在一段代码中,可能会由于各种原因抛出多种不同的异常,而对于不同的异常,我们希望用不同的方式来处理它们,而不是笼统的使用同一个方式处理,在这种情况下,可以使用异常匹配,当匹配到对应的异常后,后面的异常将不再进行匹配。

public class Demo2 {    public static void main(String[] args) {        try{            new FileInputStream("");        } catch (FileNotFoundException e) {            System.out.println("IO 异常");        } catch (Exception e) {            System.out.println("发生异常");        }    }}

在处理异常时,并不要求抛出的异常同 catch 所声明的异常完全匹配,子类的对象也可以匹配父类的处理程序。比如异常 A 继承于异常 B,那么在处理多个异常时,一定要将异常 A 放在异常 B 之前捕获,如果将异常 B 放在异常 A 之前,那么将永远匹配到异常 B,异常 A 将永远不可能执行,并且编译器将会报错。

父类的异常捕获语句不可以写在子类异常捕获语句前面
d01e8da7b35b4799c1b1577bb5e8f139.png

自定义异常

自定义一个异常类非常简单,只需要让它继承 Exception 或其子类就行。在自定义异常类的时候,建议同时提供无参构造方法和带字符串参数的构造方法,后者可以为你在调试时提供更加详细的信息。

在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。

ThrowableExceptionRuntimeException
public class Demo3 {    public static void main(String[] args) {        int number = 5;        for(int i = 4; i > -1; i--) {            if (i == 0) {                throw new MyException("这是一个异常");            }            System.out.println(number / i);        }    }}//自定义异常类 ,继承于ArithmeticExceptionclass MyException extends ArithmeticException {    //实现无参构造器    public MyException() {    }    //实现参数构造器,可将提示信息作为异常结果输出    public MyException(String msg) {        super(msg);    }}

异常堆栈

当异常抛出后,我们可以通过异常堆栈追踪程序的运行轨迹,以便我们更好的 DEBUG 。

public class Demo4 {    public static void method1() {        method2();    }    public static void method2() {        throw new NullPointerException();    }    public static void main(String[] args) {        try{            method1();        } catch (Exception e) {            // 打印堆栈轨迹            e.printStackTrace();        }    }}打印结果:java.lang.NullPointerException    at Demo4.method2(Demo4.java:10)    at Demo4.method1(Demo4.java:6)    at Demo4.main(Demo4.java:15)

通过上面的异常堆栈轨迹,在对比我们方法的调用过程,可以得出异常信息中首先打印的是距离抛出异常最近的语句,接着是调用该方法的方法,一直到最开始被调用的方法。 从下往上看 ,就可以得出程序运行的轨迹。

什么时候定义try,什么时候定义throws呢?

try

总结

异常的捕获、抛出和异常处理是维持代码健壮性的重要条件。灵活使用异常及处理,不仅能最大限度的避免出错,也能增加软件的容错机制。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值