Java 异常(一) 异常概述及其架构

一、异常概述

(一)、概述

Java异常是Java提供的一种识别及响应错误的一致性机制。异常指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
Java异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性。在有效使用异常的情况下,异常能清晰的回答 what, where, why 这3个问题:异常类型回答了“什么”被抛出,异常堆栈跟踪回答了“在哪“抛出,异常信息回答了“为什么“会抛出。

(二)、异常体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception,平常所说的异常指java.lang.Exception

Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。异常和错误的区别是:异常能被程序本身可以处理,错误是无法处理。

1、Throwable:Throwable是 Java 语言中所有错误或异常的超类。Throwable包含两个子类: Error 和 Exception。它们通常用于指示发生了异常情况。

Throwable包含了其线程创建时线程执行堆栈的快照,它提供了printStackTrace()等接口用于获取堆栈跟踪数据等信息。

Throwable常用API:

public void printStackTrace() // 打印异常的详细信息。包含了异常的类型,异常的原因,还包括异常出现的位置。
public String getMessage() // 获取发生异常的原因。
public String toString() // 获取异常的类型和异常描述信息。

2、Error:严重错误Error,无法通过处理的错误,只能事先避免。

3、Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。

(三)、异常分类

我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。

异常主要分为两大类:编译期异常和运行期异常。

编译期异常:checked异常。在编译期,就会检查,如果没有处理异常,则编译失败(如日期格式化异常)。

特点: Java编译器会检查它。此类异常,要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译。例如,CloneNotSupportedException就属于被检查异常。当通过clone()接口去克隆一个对象,而该对象对应的类没有实现Cloneable接口,就会抛出CloneNotSupportedException异常。被检查异常通常都是可以恢复的。

运行期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)(如数学异常)。

特点: Java编译器不会检查它。也就是说,当程序中可能出现这类异常时,倘若既"没有通过throws声明抛出它",也"没有用try-catch语句捕获它",还是会编译通过。例如,除数为零时产生的ArithmeticException异常,数组越界时产生的IndexOutOfBoundsException异常,fail-fail机制产生的ConcurrentModificationException异常等,都属于运行时异常。

虽然Java编译器不会检查运行时异常,但是我们也可以通过throws进行声明抛出,也可以通过try-catch对它进行捕获处理。

如果产生运行时异常,则需要通过修改代码来进行避免。例如,若会发生除数为零的情况,则需要通过代码避免该情况的发生!

二、异常处理

Java异常处理机制用到的几个关键字:try、catch、finally、throw、throws。

  • try:用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
  • catch:用于捕获异常。catch用来捕获try语句块中发生的异常。
  • finally:finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
  • throw:用于抛出异常。
  • throws:用在方法签名中,用于声明该方法可能抛出的异常。

三、异常注意点

(一)、finally中的异常会覆盖(消灭)前面try或者catch中的异常

  • 不要在fianlly中使用return。
  • 不要在finally中抛出异常。
  • 减轻finally的任务,不要在finally中做一些其它的事情,finally块仅仅用来释放资源是最合适的。
  • 将尽量将所有的return写在函数的最后面,而不是try ... catch ... finally中。

(二)、多个异常使用捕获

  • 多个异常分别处理。
  • 多个异常一次捕获,多次处理。
  • 多个异常一次捕获一次处理。

一般情况下,一般我们是使用一次捕获多次处理方式,如下代码

try{
// 编写可能会出现异常的代码
}catch(异常类型A e){ 当try中出现A类型异常,就用该catch来捕获.
// 处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}catch(异常类型B e){ 当try中出现B类型异常,就用该catch来捕获.
// 处理异常的代码
//记录日志/打印异常信息/继续抛出异常
}

注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

三、实例

(一)、try - catch用法

try - catch 必须搭配使用,不能单独使用。

public class ExceptionDemo {
public static void main(String[] args) {
try {
int i = 10 / 0;// 除数不能为0,此行会抛出 ArithmeticException 异常
System.out.println("i = " + i);// 抛出异常后,此行不会执行
}catch(ArithmeticException e) { // 捕获 ArithmeticException 异常
// 在catch 代码块处理异常
e.printStackTrace(); // 异常最详细信息
System.out.println("e.getMessage() : " + e.getMessage());// 发生异常的原因
System.out.println("e.toString() : " + e.toString()); // 获取异常的类型和异常描述信息
}
}
}

(二)、finally 用法

try - catch - finally搭配使用,或者 try - finally 搭配使用。

public class ExceptionDemo {
public static void main(String[] args) {
// try-catch-finally搭配使用
try {
int[] arr = {1,2,3};
int i = arr[3];// 数组索引越界,此行会抛出 ArrayIndexOutOfBoundsException 异常
System.out.println("i = " + i);// 抛出异常后,此行不会执行
}catch(ArithmeticException e) { // 捕获 ArithmeticException
System.out.println(e.getMessage());// 发生异常的原因
System.exit(0); // 程序强制退出,finally 代码块不会执行
}finally {// 除了程序强制退出,如(System。exit(0)),无论是否发生异常,finally 代码块总会执行
System.out.println("this is finally");
} // try-finally搭配使用
try {
int[] arr = {1,2,3};
int i = arr[3];// 数组索引越界,此行会抛出 ArrayIndexOutOfBoundsException 异常
System.out.println("i = " + i);// 抛出异常后,此行不会执行
}finally {
// 无论是否发生异常,finally 代码块总会执行
System.out.println("this is finally");
}
}
}

注意点:

  • try-catch-finally 搭配:这种形式捕获异常时,开发者可以在 catch 代码块中处理异常(如打印日志、日志记录等),异常处理权在开发者。
  • try-finally 搭配:这种形式捕获异常时,默认抛出给 JVM 处理,JVM默认处理时调用 e.printStackTrace() 方法打印异常详细信息。
  • finally 代码块:除非程序强制退出,否则无论程序是否发生异常,finally 代码块总会执行。
  • finally 中抛出异常会覆盖(消灭)前面 try 或者 catch 中的异常,尽量避免在 finally 代码块中抛出异常。
  • 如果 try 中和 finally 中都有 return 语句,程序会先执行 finally 中的 return 语句,然后程序块运行结束,而不会执行 try 中的 return 语句。所以尽量不在finally中使用 return 语句。

(三)、throw 用法

throw 是用于抛出异常,将这个异常对象传递到调用者处,并结束当前方法的执行

public static void main(String[] args) {
  try {
    int i = 10 / 0;
    System.out.println("i = " + i);
  }catch(ArithmeticException e) {
    // 抛出异常,传递自定义异常信息提示
    // 默认抛出给 JVM 处理打印异常详细信息
    throw new ArithmeticException("除数不能为0");
  }
}

(四)、throws 用法

throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。

public class ExceptionDemo {
public static void main(String[] args) {
demo();
}
public static void demo() throws ArrayIndexOutOfBoundsException{
try {
int[] arr = {1,2,3};
int i = arr[3];
System.out.println("i = " + i);
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println(e.toString());
}
}
}

Java 异常(一) 异常概述及其架构的更多相关文章

  1. Java开源生鲜电商平台-异常模块的设计与架构(源码可下载)

    Java开源生鲜电商平台-异常模块的设计与架构(源码可下载) 说明:任何一个软件系统都会出现各式各样的异常与错误,我们需要根据异常的情况进行捕获与分析,改善自己的代码,让其更加的稳定的,快速的运行,那 ...

  2. Java笔记(十七)……异常

    异常概述 异常是什么 是对问题的描述,将问题进行对象的封装 异常体系 Throwable |---Error |---Exception |---RuntimeException 异常体系的特点 异常 ...

  3. 牛客网Java刷题知识点之什么是异常、异常处理的原理是什么、为什么要使用异常、异常体系、运行时异常、普通异常、自定义异常、异常链

    不多说,直接上干货! 在这个世界不可能存在完美的东西,不管完美的思维有多么缜密,细心,我们都不可能考虑所有的因素,这就是所谓的智者千虑必有一失.同样的道理,计算机的世界也是不完美的,异常情况随时都会发 ...

  4. 夯实Java基础系列10:深入理解Java中的异常体系

    目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...

  5. 【java基础之异常】死了都要try,不淋漓尽致地catch我不痛快!

    目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...

  6. 【java基础之异常】死了都要try

    目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...

  7. Core Java 总结(异常类问题)

    所有代码均在本地编译运行测试,环境为 Windows7 32位机器 + eclipse Mars.2 Release (4.5.2) 2016-10-17 整理 下面的代码输出结果是多少?为什么?并由 ...

  8. Java笔记:异常

    Exception 类的层次 所有的异常类是从 java.lang.Exception 类继承的子类. Exception 类是 Throwable 类的子类.除了Exception类外,Throwa ...

  9. 【Java心得总结二】浅谈Java中的异常

    作为一个面向对象编程的程序员对于 下面的一句一定非常熟悉: try { // 代码块 } catch(Exception e) { // 异常处理 } finally { // 清理工作 } 就是面向 ...

随机推荐

  1. Spring官网阅读(十四)Spring中的BeanWrapper及类型转换

    文章目录 接口定义 继承关系 接口功能 1.PropertyEditorRegistry(属性编辑器注册器) 接口定义 PropertyEditor 概念 Spring中对PropertyEditor ...

  2. 保姆式教学:Typora+图床功能

    众所周知,markdown编辑器typora是一款很好的可视化.所见即所得型的编辑器! 但是,因为图片问题,本菜狗常常不能把某些写好的markdown文档直接复制粘贴进博客而不加修改-- 不过,前几天 ...

  3. Day_09【常用API】扩展案例5_获取长度为5的随机字符串,字符串由随机的4个大写英文字母和1个0-9之间(包含0和9)的整数组成

    分析以下需求,并用代码实现 1.定义String getStr(char[] chs)方法 功能描述:获取长度为5的随机字符串,字符串由随机的4个大写英文字母和1个0-9之间(包含0和9)的整数组成 ...

  4. LiteAI四大技术"杀手锏",解锁物联网智能设备AI开发难关

    你知道我们生活中常见的物联网智能设备融合AI技术后,会给我们带来什么样的智能交互体验?在我们指尖触碰的那一刹那背后隐藏的代码世界又是怎么样的呢? 今天就来和大家说说IoT智能设备轻松实现AI的奥秘! ...

  5. python 基础知识5-集合

    1.集合set概念: 集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的.以下是集合最重要的两点: 1.去重,把一个列表变成集合, ...

  6. 说一说JS的IIFE

    1. 定义IIFE: Immediately Invoked Function Expression,意为立即调用的函数表达式,也就是说,声明函数的同时立即调用这个函数.对比一下,这是不采用IIFE时 ...

  7. Unsafe类初探

    Unsafe类是java中非常特别的一个类.它名字就叫做"不安全",提供的操作可以直接读写内存.获得地址偏移值.锁定或释放线程. 通过正常途径是无法获得Unsafe实例的,首先它的 ...

  8. nginx配置之负载均衡

    nginx负载均衡 nginx代理机分发到多台同一项目的服务机 负载均衡器代理机配置:nginx.conf的http{}: #代理池,运行在不同服务机的程序 upstream loadtest{ se ...

  9. MySQL的转义字符“\”

    \0    一个ASCII  0  (NUL)字符.    \n    一个新行符.    \t    一个定位符.    \r    一个回车符.    \b    一个退格符.    \'    ...

  10. netty 实现简单的rpc调用

    yls 2020/5/23 netty 实现简单rpc准备 使用netty传输java bean对象,可以使用protobuf,也可以通过json转化 客户端要将调用的接口名称,方法名称,参数列表的类 ...