Java异常(超详细!)

2023-11-10

1、什么是异常,java提供异常处理机制有什么用?

  • 什么是异常:程序执行过程中的不正常情况。
  • 异常的作用:增强程序的 健壮性

eg.

public class ExceptionTest01 {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        // 实际上JVM在执行到此处的时候,会new异常对象:new ArithmeticException("/ by zero");
        // 并且JVM将new的异常对象抛出,打印输出信息到控制台了。
        int c = a / b;
        System.out.println(a + "/" + b + "=" + c);

        // 此处运行也会创建一个:ArithmeticException类型的异常对象。
        System.out.println(100 / 0);
    }
}

2、java语言中异常是以什么形式存在的呢?

异常在java中以 的形式存在,每一个 异常类 都可以创建 异常对象

eg.

public class ExceptionTest02 {
    public static void main(String[] args) {
        // 通过“异常类”实例化“异常对象”
        NumberFormatException nfe = new NumberFormatException("数字格式化异常!");
        
        // java.lang.NumberFormatException: 数字格式化异常!
        System.out.println(nfe);
    }
}

3、异常继承结构图

在这里插入图片描述

  • Exception的直接子类:编译时异常(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错,因此得名编译时异常。)。
  • RuntimeException:运行时异常。(在编写程序阶段程序员可以预先处理,也可以不管,都行。)

4、异常的分类

异常分为 编译时异常运行时异常

所有异常都是在 运行阶段 发生的。因为只有程序运行阶段才可以 new对象。

因为异常的发生就是 new异常对象

4.1编译时异常因为什么而得名?

因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,因此得名。

4.2 编译时异常和运行时异常的区别?

  • 编译时异常一般发生的概率 比较高
  • 运行时异常一般发生的概率 比较低
  • 编译时异常发生概率较高,需要在运行之前对其进行 预处理
  • 运行时异常发生概率较低,没必要提前进行预处理。

4.3编译时异常和运行时异常别称

  • 编译时异常
  1. 受检异常:CheckedException
  2. 受控异常
  • 运行时异常
  1. 未受检异常:UnCheckedException
  2. 非受控异常

1、补充:

public class ExceptionTest03 {
    public static void main(String[] args) {
        System.out.println(100 / 0);

        // 这里的HelloWorld没有输出,没有执行。
        System.out.println("Hello World!");
    }
}

程序执行到System.out.println(100 / 0);
此处发生了 ArithmeticException 异常,底层 new 了一个ArithmeticException异常对象,然后抛出了。
由于是 main方法 调用了100 / 0,所以这个异常ArithmeticException抛给了main方法
main方法没有处理,将这个异常自动抛给了 JVMJVM最终终止程序的执行

此时System.out.println("Hello World!");并不会执行。

注意:
ArithmeticException 继承 RuntimeException,属于 运行时异常。在编写程序阶段不需要对这种异常进行预先的处理。


eg.

public class ExceptionTest04 {
    public static void main(String[] args) {
        // main方法中调用doSome()方法
        // 因为doSome()方法声明位置上有:throws ClassNotFoundException
        // 我们在调用doSome()方法的时候必须对这种异常进行预先的处理。
        // 如果不处理,编译器就报错。
        //编译器报错信息: Unhandled exception: java.lang.ClassNotFoundException
        doSome();
    }

    /**
     * doSome方法在方法声明的位置上使用了:throws ClassNotFoundException
     * 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常。
     * 叫做类没找到异常。这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常。
     * @throws ClassNotFoundException
     */
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!!");
    }
}

解决方法一、throws上报给方法调用者(推卸责任:调用者知道)

public class ExceptionTest04 {
    public static void main(String[] args) throws ClassNotFoundException {
        doSome();
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!!");
    }
}

解决方法二、try…catch捕捉,处理(调用者是不知道)

public class ExceptionTest04 {
    public static void main(String[] args) {
        try {
            doSome();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!!");
    }
}

5、异常的处理方式

5.1 throws

在方法声明的位置上使用 throws 关键字抛出,谁调用我这个方法,我就抛给谁。抛给 调用者 来处理。

这种处理异常的态度:上报

5.2 try…catch

这个异常不会上报,自己把这个事儿处理了。
异常抛到此处为止,不再上抛了。

注意:

  • 只要异常没有捕捉,采用上报的方式,此方法的 后续代码不会执行
  • try语句块中的某一行出现异常,该行 后面的代码不会执行
  • try…catch捕捉异常之后,后续代码可以执行。

eg.

private static void m1() throws FileNotFoundException {
    System.out.println("m1 begin");
    m2();
    // 以上代码出异常,这里是无法执行的。
    System.out.println("m1 over");
}
try {
    m1();
    // m1方法出异常,下面代码不执行。
    System.out.println("hello world!");//不执行
} catch (FileNotFoundException e){ 
	//异常处理
    System.out.println("出异常了!!");
    System.out.println(e); 
}
System.out.println("hello world"); //会执行

注意:

  • 异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。
  • 一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM。JVM只有终止。
  • 一般main方法中的异常建议使用try…catch进行捕捉。

注意:

try {
    
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

这个分支中可以使用e引用,e引用 保存的内存地址是那个new出来 异常对象的内存地址


6、在以后开发中,处理编译时异常,应该上报还是捕捉呢?

  • 如果希望调用者来处理,选择throws上报。
  • 其它情况使用捕捉的方式。

7、深入try…catch

  1. catch后面的小括号中的类型可以是 具体的异常类型,也可以是该异常类型的 父类型
  2. catch可以写多个。建议catch的时候,精确的一个一个处理。这样有利于程序的调试。
  3. catch写多个的时候,从上到下,必须遵守 从小到大

eg.

try {
	FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx");
} catch(FileNotFoundException e) {
	System.out.println("文件不存在!");
}

等同于

try {
	FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx");
} catch(Exception e) {// 多态:Exception e = new FileNotFoundException();
	System.out.println("文件不存在!");
}
try {
    FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx");
    fis.read();
} catch(IOException e){
    System.out.println("读文件报错了!");
} catch(FileNotFoundException e) {
    System.out.println("文件不存在!");
}
  1. JDK8的新特性:
    catch() 异常间可以自小到大| 分割

eg.

try {
    //创建输入流
    FileInputStream fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx");
    // 进行数学运算
    System.out.println(100 / 0); // 这个异常是运行时异常,编写程序时可以处理,也可以不处理。
} catch(FileNotFoundException | ArithmeticException | NullPointerException e) {
    System.out.println("文件不存在?数学异常?空指针异常?都有可能!");
}

8、异常两个重要方法

方法名 作用
String getMessage() 返回异常的详细消息字符串
void printStackTrace() 追踪堆栈异常信息(采用异步线程)

9、finally字句

在finally子句中的代码是最后执行的,并且是 一定会执行 的,即使try语句块中的代码出现了异常。

finally子句必须和try一起出现,不能单独编写。

9.1 finally语句通常使用在哪些情况下呢?

通常在finally语句块中完成 资源的释放/关闭

eg.

public class ExceptionTest10 {
    public static void main(String[] args) {
        FileInputStream fis = null; // 声明位置放到try外面。这样在finally中才能用。
        try {
            fis = new FileInputStream("D:\\Download\\Javabean-addperson案例解析.docx");
            String s = null;
            // 这里一定会出现空指针异常!
            s.toString();
            System.out.println("hello world!");

            // 流使用完需要关闭,因为流是占用资源的。
            // 即使以上程序出现异常,流也必须要关闭!
            // 放在这里有可能流关不了。
            //fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch(IOException e){
            e.printStackTrace();
        } catch(NullPointerException e) {
            e.printStackTrace();
        } finally {
            System.out.println("hello 浩克!");
            // 流的关闭放在这里比较保险。
            // finally中的代码是一定会执行的。
            // 即使try中出现了异常!
            if (fis != null) { // 避免空指针异常!
                try {
                    // close()方法有异常,采用捕捉的方式。
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

9.2try和finally联用,没有catch

eg.

public class ExceptionTest11 {
    public static void main(String[] args) {
    	try {
            System.out.println("try...");
            return;
        } finally {
            System.out.println("finally...");
        }

        // 这里不能写语句,因为这个代码是无法执行到的。
        //System.out.println("Hello World!");
    }
}

以下代码的执行顺序:

  1. 先执行try…
  2. 再执行finally…
  3. 最后执行 return (return语句只要执行方法必然结束。)

注意:

  • try不能单独使用。
  • try finally可以联合使用。
  • 放在finally语句块中的代码是一定会执行的

9.3 finally子句失效

System.exit(0); 只有这个可以治finally。

public class ExceptionTest12 {
    public static void main(String[] args) {
        try {
            System.out.println("try...");
            // 退出JVM
            System.exit(0); // 退出JVM之后,finally语句中的代码就不执行了!
        } finally {
            System.out.println("finally...");
        }
    }
}

9.4 finally面试题

public class ExceptionTest13 {
    public static void main(String[] args) {
        int result = m();
        System.out.println(result); //100
    }

    /*
    java语法规则(有一些规则是不能破坏的,一旦这么说了,就必须这么做!):
        java中有一条这样的规则:
            方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法!)
        java中海油一条语法规则:
            return语句一旦执行,整个方法必须结束(亘古不变的语法!)
     */
    public static int m(){
        int i = 100;
        try {
            // 这行代码出现在int i = 100;的下面,所以最终结果必须是返回100
            // return语句还必须保证是最后执行的。一旦执行,整个方法结束。
            return i;
        } finally {
            i++;
        }
    }
}

反编译之后的效果:

public static int m(){
    int i = 100;
    int j = i;
    i++;
    return j;
}

9.5 final finally finalize有什么区别?

  • final 关键字
  1. final修饰的无法继承
  2. final修饰的方法无法覆盖
  3. final修饰的变量不能重新赋值
  • finally 关键字
  1. finally 和try一起联合使用。
  2. finally语句块中的代码是必须执行的。
  • finalize 标识符
  1. 是一个Object类中的方法名。
  2. 这个方法是由垃圾回收器GC负责调用的

10、自定义异常(开发中常用)

10.1前言

SUN提供的JDK内置的异常肯定是不够的用的。在实际的开发中,有很多业务,这些业务出现异常之后,JDK中都是没有的。和业务挂钩的。因此需要自定义异常。

10.2自定义异常步骤

  1. 第一步:编写一个类继承 Exception 或者 RuntimeException.
  2. 第二步:提供两个 构造方法,一个无参数的,一个带有String参数的。

eg.

//栈操作异常:自定义异常!
public class StackOperationException extends Exception{ // 编译时异常!
    public MyStackOperationException(){

    }

    public MyStackOperationException(String s){
        super(s);
    }
}

11、方法覆盖,时遗留的问题

  • 重写之后的方法不能比重写之前的方法抛出更多(更宽泛)的异常,可以更少。方法覆盖
class Animal {
    public void doSome(){

    }

    public void doOther() throws Exception{

    }
}

class Cat extends Animal {

    // 编译正常。
    public void doSome() throws RuntimeException{

    }

    // 编译报错。
    /*public void doSome() throws Exception{

    }*/

    // 编译正常。
    /*public void doOther() {

    }*/

    // 编译正常。
    /*public void doOther() throws Exception{

    }*/

    // 编译正常。
    public void doOther() throws NullPointerException{

    }
}

注意:
一般不会这样考虑,方法覆盖复制一份,然后重写就好了。

12、总结异常中的关键字

  • 异常捕捉:
  1. try
  2. catch
  3. finally
  • throws 在方法声明位置上使用,表示上报异常信息调用者
  • throw 手动抛出异常

eg.

    public void pop() throws StackOperationException {
        if(index < 0){
            throw new MyStackOperationException("弹栈失败,栈已空!");//手动抛出异常
        }
    }

该方法index < 0时手动抛出异常,然后在方法里没有处理,上报给调用者,让调用者处理!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java异常(超详细!) 的相关文章

  • 中断并标签,“标签 MyLabel 丢失”

    我有这样的代码 if condition1 break MyLabel while true some code here MyLabel if condition2 break more code here 我收到此错误 标签 MyLab
  • Java:while循环冻结程序

    我正在制作一个游戏 我需要每 3 秒更新一次 JProgressBar 为此 我使用 while 循环 问题是我的程序由于 while 循环而冻结 我在其他问题中读到它 他们没有帮助我解决这个问题 我不知道如何解决 这是我的代码 publi
  • 像 Google Play 商店一样在垂直 RecyclerView 中动态不同图像水平 RecyclerView

    我一直在关注这个教程 http android pratap blogspot co za 2015 12 horizo ntal recyclerview in vertical html http android pratap blog
  • Glassfish 4 - JDBC 领域

    Glassfish 4 中的密码加密算法和摘要算法有什么区别 因为Password加密算法不能为空 所以我使用了MD5 Encoding使用了Hex 摘要算法为空 因此默认为 SHA 256 但是 如果我使用 JAAS 制作一个简单的登录应
  • WSDL2Java 抛出无法找到主类:org.apache.axis.wsdl.WSDL2Java

    我正在尝试从远程 Web 服务创建 java 文件 我下载了axis 1 4 将lib文件夹复制到c data axis lib其中包含这些文件 axis jar 轴 ant jar commons discovery 0 2 jar co
  • SSLContext 初始化

    我正在看JSSE参考指南 我需要获取一个实例SSLContext为了创建一个SSLEngine 所以我可以使用它Netty以启用安全性 获取实例SSLContext I use SSLContext getInstance 我看到该方法被重
  • Eclipse RCP - 将视图与编辑器区域堆叠?

    在开发 Eclipse RCP 应用程序时 是否可以将视图与编辑器区域堆叠在一起 像这样 我有多个列表 表格 我想创建一种预览组合 当通过单击鼠标选择列表上的项目时 我希望我的预览合成显示该项目的数据 如果用户双击某个项目 我想在预览合成后
  • 如何在 Java 中使用 HTML 解析器和 Apache Tika 来提取所有 HTML 标签?

    我下载了 tika core 和 tika parser 库 但找不到将 HTML 文档解析为字符串的示例代码 我必须删除网页源的所有 html 标签 我能做些什么 如何使用 Apache Tika 进行编码 您想要 html 文件的纯文本
  • 自 JRE 1.7.0_25 起,Batik 无法进行转换

    自从我更新到 JAVA 1 7 0 25 以来 蜡染在应用转换时会抛出异常 堆栈跟踪是 java awt image ImagingOpException Unable to transform src image at java awt
  • Java 声音可视化器

    我正在尝试制作一个java声音可视化工具 但我完全不知道如何在实时处理音频后立即从提取的音频中获取字节 我可以将程序与 wav 文件同步 但这不是我想要做的 我想用程序生成声音 然后播放它 而不将其保存在任何地方 谢谢您的帮助 本文可以帮助
  • java中永远不会出现的异常

    我为点和向量编写一个类 我想用它们来计算向量的点和范数 这些是点类和向量类 public class Point public float x y public class MyVector public Point start end 我
  • 用于 Eclipse 的 Resharper [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Jersey 和 Spring 中的全局异常处理?

    我正在使用 Jersey 和 Spring 3 2 以及 Open CMIS 开发 RESTful Web 服务 我没有使用 Spring 的 MVC 模式 它只是 Spring IOC 和 Jersey SpringServlet 控制器
  • Java DNSLookup MX 记录列表。类似于 MXToolBox

    我正在构建一个程序来列出域的所有 MX 记录 起初似乎工作正常 但与在线工具进行比较后http mxtoolbox com http mxtoolbox com 有些域程序无法获取 MX 记录 而 MXToolbox 可以 我不确定原因是什
  • 将一个整数从 C 客户端发送到 Java 服务器

    我使用此代码将一个整数从我的 Java 客户端发送到我的 Java 服务器 int n rand nextInt 50 1 DataOutputStream dos new DataOutputStream socket getOutput
  • java中什么是静态接口?

    我正在阅读Map Entry界面 当我注意到它是一个static界面 我不太明白什么是静态接口 它与常规接口有什么不同 public static interface Map Entry
  • Volley 在第一次调用方法时返回 null

    我正在尝试使用 volley 从服务器检索数据 但是当我第一次调用此方法时 我收到服务器的响应 但该方法返回 null 如果我第二次调用它 我会得到最后的响应 public String retrieveDataFromServer Str
  • 将 SQL 数据中的一行映射到 Java 对象

    我有一个 Java 类 其实例字段 以及匹配的 setter 方法 与 SQL 数据库表的列名相匹配 我想优雅地从表中获取一行 到 ResultSet 中 并将其映射到此类的实例 例如 我有一个 Student 类 其中包含实例字段 FNA
  • 将其元素添加到另一个列表后清除列表

    我正在做一个程序 它获取更多句子作为参数 我制作了 2 个列表 一个称为 propozitie 其中包含每个句子 另一个称为 propozitii 其中包含所有句子 问题是 当我在遇到 后清除 propozitie 列表时 它也会清除 pr
  • removeall 和removeif 的用例

    我找到了这个 fun main val list MutableList

随机推荐

  • helm简介、安装、配置、使用指南

    转载自 https blog csdn net bbwangj article details 81087911 目录 helm简介 Helm 组件及相关术语 Helm Tiller Chart Repoistory Release Hel
  • H2支持mysql:MODE=MySQL

    连接字符串参数 DB CLOSE DELAY 要求最后一个正在连接的连接断开后 不要关闭数据库 MODE MySQL 兼容模式 H2兼容多种数据库 该值可以为 DB2 Derby HSQLDB MSSQLServer MySQL Oracl
  • 在 MySQL 中,如果要存储大文本数据,改如何选择

    在 MySQL 中 如果要存储大文本数据 可以选择以下两种数据类型 TEXT 适用于存储较长的文本数据 最大长度为65 535个字符 LONGTEXT 适用于存储非常大的文本数据 最大长度为4 294 967 295个字符 选择使用哪种类型
  • 【SQL】sql语句LEFT JOIN(拼接表)详解

    1 语法 SELECT column name s FROM table1 LEFT JOIN table2 ON table1 column name table2 column name 2 说明 按照一定规则 将表table1和表ta
  • Python——将字符串写入文本保存

    sResult为要写入的内容 一般是字符串形式 with open C Python37 911 txt w encoding utf 8 as f f write str sResult f close
  • stm32 利用定时器中断消除按键抖动

    button c int iButtonCount i代表int型变量 ButtonCount表示按键计数变量 int iButtonFlag i代表int型变量 ButtonFlag表示重按键标志 1代表重新按键 0为没有重新按键 int
  • Android studio的cMake编译生成.so库并调用

    第一步 添加工具 在SDK Tools中勾选安装CMake LLDB NDK 其中的LLDB是调试本地代码的工具 可以调试C 代码 第二步 创建一个最简单的官方demo File gt New gt NewProject 选中最下方的Inc
  • 前端实战系列:如何开发微信小程序

    课程简介 小程序开发相对于App开发 开发快捷推广成本低 依托微信平台非常好推广 市面上很多企业现在都想开发自己的小程序 本次课程带大家开发一个小程序 从账号注册到编写全流程讲解 实现一个 本地生活案例 课程推荐 前端实战 如何开发微信小程
  • React 高频面试题-大厂必问

    React 对于react的理解 一 是什么 React 用于构建用户界面的JavaScript库 只提供UI层面的解决方案 遵循组件设计模式 声明式编程范式和函数式编程概念 以使前端应用程序更高效 使虚拟 DOM 来有效的操作 DOM 遵
  • C#(64位系统) 解决"未能加载文件或程序集,或它的某一个依赖项..."

    这个问题通常出在引用第三方DLL或者自己以前写的DLL 在64位系统下则可能会出现这种问题 今天下载MySQLDriverCS后引用遍出现了这个问题 参考了一些文档 下面给出解决方法 将项目的生成目标平台改为x86 默认Any cpu 就可
  • $stateProvider

    stateProvider工作的方式与Angular s v1 router相近 但是他更加注重状态 状态对应于应用程序中某个位置 整体的UI和导航A state corresponds to a place in the applicat
  • 基于matlab实现的人脸检测

    作为一个图像处理的初学者 一直想写一个人脸检测的程序 经过多次尝试 发现不管是在C站上找的开源代码 还是自己手撸的代码 总是那么不尽人意 后来经过查阅资料 发现matlab内置有一个人脸检测的检测器函数 精度非常高 如果对人脸检测不求甚解
  • 【毕业设计】stm32机器视觉的人脸识别系统 - 单片机 物联网 嵌入式

    文章目录 0 前言 1 简介 2 主要器件 3 实现效果 4 设计原理 K210实现人脸识别 5 部分核心代码 6 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这
  • camera 驱动 mipi计算

    static struct sensor lib out info t sensor out info RES 0 x output 3264 y output 2448 line length pclk 1932 frame length
  • java之简单上手HelloWorld程序(命令行窗口操作)

    文章目录 java之简单上手HelloWorld程序 命令行窗口操作 一 下载安装JDK文件 二 查询是否安装成功 一 创建文件 二 代码部分 三 打开命令行窗口运行程序 java之简单上手HelloWorld程序 命令行窗口操作 一 下载
  • sdc时钟约束2——多驱动时钟

    多驱动时钟 前言 在设计中 难免会遇到多个时钟通过mux选择后作为模块时钟使用的情况 在设置sdc时需要定义 为避免在使用pt分析时序时没有分析全 而出现时序违列 需要在创建时钟时注明 提示 以下是本篇文章正文内容 下面案例可供参考 如图所
  • 简单的递归下降语法分析程序

    简单递归分析程序 其代码如下 include
  • 计算机无法启用媒体流,电脑流媒体打不开怎么回事?电脑打开媒体流的方法

    流媒体是边传边播的媒体 它采用流式传输的方式在Internet播放媒体 电脑开启媒体流服务后 我们可以方便的传送多媒体文件 有的网友反馈说电脑流媒体打不开 这是怎么回事 可能是第三方优化软件无意禁用相关服务导致的 下面就来分享电脑流媒体打不
  • 代驾小程序源码全套,支持二开(Thinkphp+bootstrap+小程序uniapp)

    代驾小程序源码全套 支持二开 Thinkphp bootstrap 小程序uniapp 支持二开 包含基本的代驾功能 内部基于腾讯地图开发 1 基于ThinkPHP Bootstrap的极速后台代驾系统 2 基于uniapp开发的代驾小程序
  • Java异常(超详细!)

    1 什么是异常 java提供异常处理机制有什么用 什么是异常 程序执行过程中的不正常情况 异常的作用 增强程序的 健壮性 eg public class ExceptionTest01 public static void main Str