Java OOP 6 异常

文章目录

  • Java OOP 6 异常
    • 一、学习目标
    • 二、生活中的异常
    • 三、程序中的异常
    • 四、什么是异常
    • 五、程序中的异常处理
    • 六、异常处理
    • 七、常用的异常处理结构
    • 八、try-catch块
    • 九、try-catch-finally
    • 十、多重catch块
    • 十一、异常的分类
    • 十二、运行时异常
    • 十三、Checked异常
    • 十四、Checked异常处理示例
    • 十五、异常处理的完整流程
    • 十六、声明异常
    • 十七、抛出异常
    • 十八、自定义异常
    • 十九、自定义异常的应用场景
    • 二十、日志记录框架
    • 二十一、本章总结

一、学习目标

  1. 熟练使用try-catch-finally进行异常处理
  2. 理解Java异常处理机制的执行过程
  3. 会使用throws声明异常
  4. 会使用throw抛出异常
  5. 了解异常的分类
  6. 会使用log4j2记录日志

二、生活中的异常

三、程序中的异常

丰收时节,星沐生态农场将采摘的水果平均分给每家果商,编程实现计算每家果商可以分到的蔬果重量

/*** 计算果商供应量*/
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");System.out.println("欢迎再来,预祝生意兴隆!");}
}

接受的果商数值直接影响代码的运行结果

  • 正整数:程序正常运行

  • 零:程序出现异常

  • 非数字:程序出现异常

因为疏漏造成程序运行出现异常,应该怎么解决?是否可以让程序自动判断异常和处理异常呢?

代码改造如下,尝试通过if-else语句解决

package com.aiden.exceptions.demo02;import java.util.Scanner;/*** 计算每家果商供应量(使用if-else处理异常)*/
public class Test2 {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.print("请输入果实采摘量(公斤):");int weight = 0;if (input.hasNextInt()) {weight = input.nextInt();} else {System.err.println("果实采摘量必须是整数!");System.exit(1);}System.out.print("请输入果商数(家):");int num = 0;if (input.hasNextInt()) {num = input.nextInt();if (num <= 0) {System.err.println("果商数必须大于零!");System.exit(1);}} else {System.err.println("果商数必须输入整数!");System.exit(1);}System.out.println("每家果商供应" + weight / num + "公斤水果。");System.out.println("欢迎再来,预祝生意兴隆!");}
}

使用if else的缺陷

  1. 无法穷举所有的异常情况
  2. 影响程序可读性,维护难度高

解决方案:使用异常处理机制

四、什么是异常

异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序

生活中遇到异常时的处理方案

生活中,根据不同的异常进行相应的处理,而不会就此中断我们的生活

五、程序中的异常处理

Java编程语言使用异常处理机制为程序提供了错误处理的能力

  1. Java中,所有的异常都定义为类
  2. 除了内置的异常类之外,Java也可以自定义异常类
  3. Java的异常处理机制也允许自行抛出异常

六、异常处理

Java的异常处理是通过5个关键字实现的

① try、② catch、 ③finally、④throw、⑤ throws

七、常用的异常处理结构

关键字try、catch、 finally 组成常用的异常处理结构

try {//有可能出现异常的语句
}[catch(异常类型 异常对象) {//异常处理语句
}] [finally {//一定会运行到的语句
}]

八、try-catch块

使用try-catch块捕获异常,分为三种情况

第一种情况(正常)

public static void main(String[] args) {try {// 代码段(此处不会产生异常)} catch (异常类型 ex) {// 对异常进行处理的代码段}// 代码段
}

第二种情况:出现异常

public static void main(String[] args) {try {// 代码段 1// 产生异常的代码段 2// 代码段 3} catch (异常类型 ex) {// 对异常进行处理的代码段4}// 代码段5
}

示例:使用try-catch语句处理接受果商数为0的异常

package com.aiden.exceptions.demo03;import java.util.Scanner;/*** 使用try-catch语句处理异常*/
public class Test3 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");System.out.println("欢迎再来,预祝生意兴隆!");} catch (Exception ex) {//捕捉异常,提示出错信息System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");}}
}

运行结果:

在catch块中处理异常

加入用户自定义处理信息

System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零! ");

调用方法输出异常信息

e.printStackTrace();

异常对象常用的方法

方法名 说 明
void printStackTrace() 输出异常的堆栈信息
String getMessage() 返回异常信息描述字符串, 是printStackTrace()输出信息的一部分

printStackTrace()的堆栈跟踪功能显示出程序运行到当前类的执行流程

 try {//省略代码} catch (Exception ex) {System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");ex.printStackTrace();  //输出完整异常信息}

第三种情况:异常类型不匹配

public static void main(String[] args) {try {// 代码段 1// 产生异常的代码段 2// 代码段 3} catch (异常类型 ex) {// 对异常进行处理的代码段4}// 代码段5
}

九、try-catch-finally

在try-catch块后加入finally块
是否发生异常都执行

示例:使用try-catch-finally语句处理果商数为0的异常

package com.aiden.exceptions.demo05;
/*** 使用try-catch-finally语句处理异常(输出完整异常信息)*/import java.util.Scanner;public class Test5 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");} catch (Exception ex) {System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");ex.printStackTrace();} finally {//无论是否出现异常,都会执行finally块中代码System.out.println("欢迎再来,预祝生意兴隆!");}}
}

运行结果:

在try-catch块后加入finally块,当存在 return的try-catch-finally块

示例代码: try 和 finally语句块中存在return语句

package com.aiden.exceptions.demo06;import java.util.Scanner;/*** 使用try-catch-finally语句处理异常(异常处理中使用return)*/
public class Test6 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");return;//不影响finally块执行} catch (Exception ex) {System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");ex.printStackTrace();return;//不影响finally块执行} finally {System.out.println("欢迎再来,预祝生意兴隆!");}}
}

运行结果

finally唯一不执行的情况

示例代码

package com.aiden.exceptions.demo07;/*** 使用try-catch-finally语句处理异常(finally不被执行的情况)*/import java.util.Scanner;public class Test7 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");} catch (Exception ex) {System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");ex.printStackTrace();System.exit(1);  //finally语句块不被执行的唯一条件} finally {System.out.println("欢迎再来,预祝生意兴隆!");}}
}

运行结果

十、多重catch块

程序中可能存在多种异常类型不同的异常类型有不同的处理方式

引发多种类型的异常

  1. 排列catch 语句的顺序:先子类后父类
  2. 发生异常时按顺序逐个匹配
  3. 只执行第一个与异常类型匹配的catch语句

示例代码

package com.aiden.exceptions.demo08;/*** 使多重catch语句*/import java.util.InputMismatchException;
import java.util.Scanner;public class Test8 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");} catch (ArithmeticException ex) {System.err.println("出现错误:果商数应大于零!");ex.printStackTrace();} catch (InputMismatchException ex) {System.err.println("出现错误:果实采摘量和果商数应为整数!");ex.printStackTrace();} catch (Exception ex) {System.err.println("其他未知错误!");ex.printStackTrace();} finally {System.out.println("欢迎再来,预祝生意兴隆!");}}
}

十一、异常的分类

十二、运行时异常

  • 是可以在程序中避免的异常
  • 当程序进行时发生异常,会输出异常堆栈信息并终止程序运行
  • 可以使用try-catch语句捕获
  • 常见的异常类型
异常类型 说明
ArithmeticException 当出现算术错误时,抛出此异常 如:一个整数“除以零”时,抛出此异常
ArrayIndexOutOfBoundsException 非法索引访问数组时抛出的异常 如索引为负或大于等于数组长度
ClassCastException 当试图将对象强制转换为非本对象类型的子类时,抛出该异常
IllegalArgumentException 表明向方法传递了一个不合法或不正确的参数
InputMismatchException 欲得到的数据类型与实际输入的类型不匹配
NullPointerException 当应用程序试图在需要对象的地方使用null时,抛出该异常
NumberFormatException 当试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常 如:把“ABC”转成数字

十三、Checked异常

  • 是指运行时异常以外的异常
  • 是用户错误或问题引起的异常
  • 程序员无法预见
  • 编译器会提示
  • 如果不进行捕获,则会出现编译错误
  • 常见的异常类型
    • FileNotFoundException异常
    • SQLException异常

十四、Checked异常处理示例

创建文件流

/*** 演示Check异常
*/
public class Test9 {public static void main(String[] args) {FileInputStream fis = null; //创建一个文件流对象File file = new File("d:\\test.txt");fis = new FileInputStream(file);//初始化文件流入对象fis.close();}
}

处理checked异常

package com.aiden.exceptions.demo09;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;/*** 演示Check异常
*/
public class Test9 {public static void main(String[] args) {FileInputStream fis = null; //创建一个文件流对象File file = new File("d:\\test.txt");try {fis = new FileInputStream(file);//初始化文件流入对象} catch (FileNotFoundException e) {e.printStackTrace();}finally {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}
}

十五、异常处理的完整流程

对于异常处理,不同项目的要求并不相同
由项目开发标准决定异常是统一使用Exception类型接收处理还是分开处理
如果开发要求严格,会对每一种异常分别进行处理,详细记录异常信息,产生一定工作量

十六、声明异常

问题

如果在一个方法体中抛出了异常,如何通知调用者?

方案

使用关键字throws声明某个方法可能抛出的各种异常

语法

public void 方法名()  throws 异常类型[,异常类型] {//方法体
}

经验

声明异常,多个异常用逗号隔开

示例: 使用关键字throw声明异常,并处理异常

package com.aiden.exceptions.demo10;/*** throws声明异常*/
import java.util.InputMismatchException;
import java.util.Scanner;public class Test10 {//实际开发中,main()方法不建议声明异常,因为如果程序出现了错误,会导致程序中断执行。//main()方法声明的异常,由Java虚拟机处理//public static void main(String[] args) throws Exception{//    calculation();//}public static void main(String[] args) {try {calculation();} catch (Exception ex) {System.err.println("出现错误:采摘量和果商数应为整数,果商数应大于零!");ex.printStackTrace();} finally {System.out.println("欢迎再来,预祝生意兴隆!");}}/*** 计算每家果商供应量* @throws Exception*/public static void calculation() throws ArithmeticException, InputMismatchException {Scanner input = new Scanner(System.in);System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();System.out.print("请输入果商数(家):");int num = input.nextInt();System.out.println("每家果商供应" + weight / num + "公斤水果。");}
}

十七、抛出异常

除了系统自动抛出异常外,有些问题需要程序员自行抛出异常

  • 根据程序逻辑自定义的异常类,在Java异常体系中并未提供,不能抛出
  • 根据业务需要自行选择异常抛出时机,或自定义异常处理逻辑

语法

throw new 异常名([参数列表]); //创建异常类的对象通过throw抛出

示例

throw new Exception();

注意

throw抛出的只能是Throwable类或其子类的对象

抛出异常示例

-某影院3~6岁儿童及60岁以上老人可以买半票25元/张,其他年龄观众需买全价票50元/张,在购票系统中,输入正常范围年龄,可提示正确票价信息;否则,输出错误提示。

package com.aiden.exceptions.demo11;import java.util.Scanner;/*** throw抛出异常*/
public class Test11 {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.print("请录入您的年龄:");int age = input.nextInt();try {Test11 test = new Test11();System.out.println(test.ShowTicketPrice(age));} catch (Exception ex) {ex.printStackTrace();}}/***根据年龄显示票价信息*/public String ShowTicketPrice(int age) throws Exception {if (age < 3) {throw new Exception("您录入的年龄有误!");} else if (age >= 60 || age <= 6) {return "您可以购买半价票25元!";} else {return "您需要购买全价票50元!";}}
}

运行结果

十八、自定义异常

当Java异常体系中提供的异常类型不能满足程序的需要时,可以自定义异常类
步骤

  1. 定义异常类,继承Exception类或者RuntimeException类
  2. 编写异常类的构造方法,并继承父类的实现
  3. 常见的构造方法
public Exception() { //构造方法1super();
}
public Exception(String message) { //构造方法2super(message);
}
public Exception(String message, Throwable cause) {  //构造方法3super(message, cause);
}
public Exception(Throwable cause) {  //构造方法4super(cause);
}

实例化自定义异常对象,并使用throw关键字抛出

自定义异常类AgeException,捕捉年龄在正常范围外的数值

package com.aiden.exceptions.demo12;/*** 年龄异常*/
public class AgeException extends Exception {public AgeException() {super();}public AgeException(String message) {super(message);}
}

测试

package com.aiden.exceptions.demo12;import java.util.Scanner;/*** 测试自定义异常*/
public class DefineExcepTest {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.print("请录入您的年龄:");int age = input.nextInt();try {ShowTicketPrice(age);} catch (AgeException ex) {ex.printStackTrace();}}/*根据年龄显示票价信息*/public static void ShowTicketPrice(int age) throws AgeException {if (age < 3) {throw new AgeException("您录入的年龄有误!");} else if (age >= 60 || age <= 6) {System.out.println("您可以购买半价票25元!");} else {System.out.println("您需要购买全价票50元!");}}
}

十九、自定义异常的应用场景

项目中因业务逻辑错误需要抛出异常,但Java中不存在这类异常例如,年龄异常、性别异常等
项目开发一般是由团队成员共同完成,为统一对外异常展示的方式,可以使用自定义异常

二十、日志记录框架

如何实现以文件形式记录异常信息?

  • 使用日志框架

日志(log)

  • 主要用来记录系统运行中一些重要操作信息
  • 便于监视系统运行情况,帮助用户提前发现和避开可能出现的问题,或者出现问题后根据日志找到原因

日志分类

  • SQL日志、异常日志、业务日志

日志的主要用途

  1. 问题追踪
  2. 状态监控
  3. 安全审计

日志框架log4j2

  • 一款非常优秀的日志框架
  • 控制日志的输出级别
  • 控制日志信息输送的目的地是控制台、文件等
  • 控制每一条日志的输出格式

使用log4j2记录日志
编写配置文件

  • 文件后缀可为.xml、.json或者.jsn

定义日志记录器Logger

  • 获取日志记录器的方式

记录日志

  1. Logger类可以替代System.out或者System.err,供开发者记录日志信息
  2. Logger类常用方法

日志记录器的日志级别

  • all:最低等级,用于打开所有日志记录
  • trace:用于程序追踪输出
  • debug:指出细粒度信息事件,对高度应用程序是非常有帮助的
  • info:在粗粒度级别上指明消息,强调应用程序的运行过程
  • warn:表示警告信息,即可能会出现的潜在错误
  • error:指出虽然发生错误事件,但仍然不影响系统的继续运行
  • fatal:指出将会严重的错误事件将会导致应用程序退出
  • OFF:最高等级的,用于关闭所有日志记录

示例

  1. 控制台和文件中同时记录日志信息
  2. 信息录入以及正常执行的情况记录为debug级别日志
  3. 发生异常的信息记录为error级别日志

格式要求

  1. 控制台输出内容:执行位置、记录日志级别及输出信息
  2. 文本日志记录内容:日期和时间(精确到秒)、执行位置、记录日志级别及输出信息

分析

实现步骤

  • 编写配置文件log4j2.xml

  • 定义日志记录器Logger

  • 记录日志

配置log4j2.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration staus="OFF"><appenders><!--输出日志到控制台的配置--><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%l] %-5level - %msg%n"/></Console><!--输出日志到文件的配置--><File name="log" fileName="log/test.log"><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%l] %-5level - %msg%n"/></File></appenders><loggers><root level="all"><appender-ref ref="Console"/><appender-ref ref="log"/></root></loggers>
</configuration>

定义日志记录器Logger,记录日志

package com.aiden.exceptions.demo13;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;import java.util.InputMismatchException;
import java.util.Scanner;/*** 使用Log4j2记录日志*/
public class Test13 {//获取Logger对象private static Logger logger = LogManager.getLogger(Test13.class.getName());public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("请输入果实采摘量(公斤):");int weight = input.nextInt();logger.debug("采摘量:" + weight);System.out.print("请输入果商数(家):");int num = input.nextInt();logger.debug("果商数:" + num);//向日志中写入Debug信息System.out.println("每家果商供应" + weight / num + "公斤水果。");logger.debug("输出结果:" + String.format("%d/%d=%d", weight, num, weight / num));} catch (ArithmeticException ex) {logger.error("输入有误,果商数应大于零!", ex);//记录日志} catch (InputMismatchException ex) {logger.error("输入有误,果实采摘量和果商数应为整数!", ex);} catch (Exception ex) {logger.error(ex.getMessage());} finally {System.out.println("欢迎再来,预祝生意兴隆!");}}
}

运行结果:

二十一、本章总结

Java OOP 6 异常相关推荐

  1. 在 Java OOP 编程中的注意事项

    在 Java OOP 编程中的注意事项 重写 方法 字段 反射 static 接口 abstract Maven JUnit 重写 方法 当子类重写超类的方法时,子类该方法的被访问权限不能低于超类方法 ...

  2. 初学Java6:Java OOP基础语法总结

    *************** Java OOP 基 础 语 法 总 结 ************************* 1,类与对象1),类(class)是相同属性和方法的一组集合. A,类的组 ...

  3. Java OOP 7 JAVA 集合框架

    Java OOP 第七章 JAVA 集合框架 文章目录 Java OOP 第七章 JAVA 集合框架 一.学习目标 二.数组存在的缺陷 三.Java集合框架 四.Collection接口 五.Coll ...

  4. JavaSE-Adventure(VII) Java OOP 面向对象程序设计

    JavaSE-Adventure(VII) Java & OOP 面向对象程序设计 CONTENTS JavaSE-Adventure(VII) Java & OOP 面向对象程序设计 ...

  5. Java OOP 9 Java I/O

    Java OOP 9 Java I/O 文章目录 Java OOP 9 Java I/O 一.学习目标 二.文件 三.File类 四.IO流 五.Java流的分类 Java流的分类 按流向划分:输入流 ...

  6. Java OOP 第三章 多态

    Java OOP 多态 文章目录 Java OOP 多态 一.学习目标 二.多态 1.为什么使用多态 2.什么是多态? 3.如何实现多态? 三.向上转型 四.父类作为形参 扩展种植梨树 五.多态的使用 ...

  7. JAVA -- OOP -- 接口

    JAVA -- OOP -- 接口 1.概念 2.格式 3.接口的特点 4.接口的定义及实现 5.接口的用法 6.接口的多继承和多实现 7.类.接口 之间的关系 8.抽象类与接口的区别 1.概念 接口 ...

  8. Java OOP 8 实用类(枚举、包装类、日期类、Random类)

    Java OOP 8 实用类 文章目录 Java OOP 8 实用类 一.学习目标 二.Java API 三.枚举 3.1为什么使用枚举? 3.2什么是枚举? 3.3如何使用枚举? 3.4常见错误 四 ...

  9. java.lang.NullPointerException异常原因及解决

    java.lang.NullPointerException异常原因是因为创建了一个引用类型的变量却没有指向任何对象而又去通过这个引用类型变量加点的形式去访问非静态的方法及属性. 给出三种情况, 第一 ...

最新文章

  1. 【openfst样例1】Tokenization
  2. UVa 164 - String Computer
  3. 屠榜大杀器UniMP!百度登顶图神经网络权威榜单三项榜首
  4. python 编码规范 PEP8整理
  5. OpenCV调整彩色图像的饱和度和亮度
  6. unity中实现简单对象池,附教程原理
  7. 网络知识:WiFi越用越慢,到底是什么原因?
  8. 三方应用集成_华为携手利尔达完成业界首个5G工业智能网关预商用集成验证
  9. 写入文件python并用序号_Python和excel表合成示例:向表中添加序列号,向表的现有内容添加索引,与,Excel,表格,综合,实例,给,增加,序号,对,已有...
  10. Python3.X出现AttributeError: module 'urllib' has no attribute 'urlopen'错误
  11. 【工具】ColorPix!分享一个超好用的桌面取色工具
  12. 带GUI界面的手写数字识别
  13. RationalDMIS 2020高级教程之变量写入EXCEL
  14. 微信java tools_微信开发工具包(weixin-java-tools)
  15. vue项目中画出优雅的线条(虚线、直线、折线、带箭头、流动效果等)
  16. PDF用什么软件可以修改
  17. 播放器实战 10 像素格式与尺寸的转换
  18. 楼教主(楼天成)的ACM心路历程
  19. BC26 TCP透传
  20. 2022年深圳市光明区防疫科技攻关支持项目申报操作指引

热门文章

  1. Java面试题以及答案--- MongoDb
  2. 数字电路硬件设计系列(十)之RS485电路设计
  3. 关于H5页面中生成图片的两种方式!
  4. 中忻嘉业科技:怎样分析抖音用户群体画像
  5. 【LaTex】\begin{array}{r},\begin{array}{l},\begin{array}{c}
  6. 触手可及的AI:2020十大人工智能APP揭榜时刻
  7. GeoServer入门学习:02-安装部署
  8. 学了go语言再学java容易吗_年纪大了还想转行当程序员,现在学java还来得及吗-Go语言中文社区...
  9. 做3D游戏建模师有年龄限制吗?
  10. 过百万,小小庆祝一下