当前位置: 首页 > news >正文

Java09 异常

异常

  • 异常
    • 1.java中的异常体系:
    • 2.运行时异常和编译时异常的区别:
    • 3.异常处理的方式
    • 4. 异常的捕获:
      • (1)使用try-catch语句对编译器(运行期)的异常进行捕获
      • (2)使用try-catch-finally进行捕获
    • 5.异常的声明:
    • 6. 异常的抛出:
    • 7. 异常的几个特点:
    • 8.自定义异常:
    • 9. 日志:Log4j
      • (1)优点:
      • (2)Log4j 是一种非常流行的日志框架:
      • (3)当使用 Log4j 输出一条日志时,Log4j 自动通过不同的Appender(输出源)把同一条日志输出到不同的目的地。
      • (4)log4j的应用:
        • 《4.1》. 添加依赖
        • 《4.2》. 创建log4j配置
        • 《4.3》log4j的应用:
        • 4.3.1:对象创建

异常

1.java中的异常体系:

1Throwable类是所有的异常的父类,此类继承于object顶级父类(2Throwable类有两个子类Exception(异常)和Error(错误)(3Exception(异常)又分为RuntimeException(运行时异常)和除RuntimeException(运行时异常)即其子类之外的异常(编译期/检查时异常)如IOException

2.运行时异常和编译时异常的区别:

(1)运行时异常指发生在程序运行期间报出的异常,此异常可进行处理,也可不进行处理(2)编译时异常指发生在程序编写的时候发生的异常(注意和语法错误区分开),此异常必须进行处理,否则程序编译无法通过

3.异常处理的方式

(1)使用throws关键字进行声明
(2)使用try-catch进行异常的捕获

4. 异常的捕获:

(1)使用try-catch语句对编译器(运行期)的异常进行捕获

《1》语法规则:

try{ //可能发生异常的代码
}catch(异常的类型 对象名){//发生异常的处理方式
}

《2》特点:

《2.1》try块中可能存在多个没有继承关系的异常类型,此时也必须用多个catch来进行捕获,如果这些异常处理方式一致,可以写只一个catch进行捕获(在catch后面的()中分别填入对应的异常类型,之间用或连接,最后再写对象名)《2.2》如果try块中出现异常,则跳出try块进入对应的catch块中,tyr块中剩余的代码和其他的catch块不在执行

《3》注意事项:

如果try块中出现的异常有继承关系,用catch捕获时,可以使用他们的共同父类进行捕获,子类的异常可直接省略(对各个异常的处理方式一致),如果不同的异常需要不同的处理方式,则需要将子类异常类型放在上面,越是父类放在越下面,如果将最父类的异常类型放在最上面,则它可以捕获try块中的所有异常,下面的catch块不会在被选择,即失去了存在的意义。

(2)使用try-catch-finally进行捕获

《1》语法规则:

public class ExceptionHandlingExample {public static void main(String[] args) {try {// 可能发生异常的代码int result = divide(10, 0); // 尝试做除法运算,会抛出 ArithmeticException 异常System.out.println("Result: " + result); // 这一行不会被执行} catch (ArithmeticException e) {// 发生异常的处理方式System.out.println("Exception caught: " + e.getMessage());} finally {// 一定会执行的代码块System.out.println("Finally block executed.");}}public static int divide(int a, int b) {return a / b; // 试图除以0,会抛出 ArithmeticException 异常}
}

《2》finally块中的代码块一定会执行(system.exit(0)除外),因此一般存在需要释放的系统资源。

《3》注意finally有几个特点:

· finally语句不是必须的,可写可不写;

· finally总是最后执行。

· 如果try或catch中有return语句,return语句在finally块执行完成后再执行,如果finally中也有return语句,则执行finally中的return语句,try或catch中的return语句不再执行。

如果没有发生异常,就正常执行try { … }语句块,然后执行finally。如果发生了异常,就中断执行try { … }语句块,然后跳转执行匹配的catch语句块,最后执行finally。可见,finally是用来保证一些代码必须执行的。

某些情况下,可以没有catch,只使用try … finally结构。

《4》使用try-with-resouce可以自动关闭系统资源:

 try(要关闭的系统资源){}catch(捕获异常){}

注意:只有实现接口Closeable或继承AutoClose的才可以关闭系统资源,手动关闭系统资源用方法close()。

5.异常的声明:

使用throws关键字进行声明,声明位置在出现异常的方法的方法名(参数)后面{的前面,如有多个异常,使用“,”隔开,对于编译期异常,必须要求声明

6. 异常的抛出:

(1)throw new 异常类型()-------执行抛出异常动作(2)如果在catch块中重新抛出异常,先执行finally块,执行完成后在抛出catch块中的异常(3)对于编译期异常,必须要在方法上声明此方法可能出现此类异常(4)对于运行时异常,在方法上声明不做强制要求。

7. 异常的几个特点:

(1)传播性:如果一个方法中抛出异常,这个异常会被不断地传播到调用这个方法的各个方法中,直到某个方法中捕获了这个异常为止。

例:

public class Main {public static void main(String[] args) {try {process1();} catch (Exception e) {e.printStackTrace();}}static void process1() {process2();}static void process2() {Integer.parseInt(null); // 会抛出NumberFormatException}
}
当 process2() 方法抛出 NumberFormatException 异常时,该异常会向上层方法传播,即传播到调用 process2() 的 process1() 方法中。
因为 process1() 方法没有处理这个异常,所以 NumberFormatException 继续传播到调用 process1() 的 main 方法中。
在 main 方法中,使用了 try-catch 块来捕获任何可能抛出的异常,包括 NumberFormatException。
当异常被捕获后,程序会执行 catch 块中的代码,输出异常信息。

异常的传播指的是,当一个方法内部抛出异常时,如果该异常没有在方法内部被捕获和处理,它会被传播到调用该方法的上层方法,直到某个方法捕获并处理了这个异常,或者直到异常传播到程序的顶层,如 main 方法。异常传播的过程中,每一层调用的方法如果没有捕获该异常,都会将异常向上传播。

(2)屏蔽:如果finally块和catch块中同时抛出异常,则只会打印出finally中的异常信息,catch块中的异常会被屏蔽。如果需要打印catch块中的异常,则需要将catch块中的异常信息添加到finally中抛出的异常中,以下述代码为例:

public class Demo09 {public static void main(String[] args) {Exception exception = null; // 定义一个异常 exceptiontry {Integer.parseInt("abc"); // 此处会抛出 NumberFormatException} catch (Exception e) { // 捕获 NumberFormatException,e = NumberFormatExceptionSystem.out.println("catch"); // 输出 catchNullPointerException ex = new NullPointerException(); // 创建新的 NullPointerExceptionex.addSuppressed(e); // 将捕获到的 NumberFormatException 添加到新的异常 ex 中exception = ex; // 将 ex 赋值给 exception,此时 exception 包含了两个异常信息throw ex; // 抛出 ex,这里的 ex 将会被 finally 块中的异常屏蔽掉} finally {System.out.println("finally"); // 输出 finallyIllegalArgumentException ex = new IllegalArgumentException(exception);// 创建新的 IllegalArgumentException,将异常 exception 传递给新的异常 exthrow ex; // 抛出此时的异常 ex,包含了之前捕获的两个异常信息}}
}

(3)转换:以下述代码为例

import java.io.UnsupportedEncodingException;public class Demo08 {public static void main(String[] args) throws UnsupportedEncodingException {test1();}private static void test1() throws UnsupportedEncodingException {try {test2();} catch (Exception e) {throw new IllegalArgumentException("参数不合法", e);}}private static void test2() throws UnsupportedEncodingException {throw new NullPointerException();}
}

在test2中抛出的异常NullPointerException传递到tsst1中被转换成了 IllegalArgumentException,

8.自定义异常:

(1)定义规范:一个常见的做法是自定义一个BaseException作为“根异常”,然后,各种业务类型的异常即可继承自BaseException。BaseException需要继承自一个适合的Exception,通常建议继承自RuntimeException:

(2)在BaseException中应提供多个构造方法:这样在抛出异常时即可选择不同的构造方法。

public class BaseException extends RuntimeException {public BaseException() {super();}public BaseException(String message, Throwable cause) {super(message, cause);}public BaseException(String message) {super(message);}public BaseException(Throwable cause) {super(cause);}
}

9. 日志:Log4j

(1)优点:

1.可以设置输出级别,禁止某些级别输出。例如,  只输出错误日志;
2.可以被重定向到文件,这样可以在程序运行结束后查看日志;
3.可以按包名控制日志级别,只输出某些包打的日志;
4.可以规范项目开发

(2)Log4j 是一种非常流行的日志框架:

Log4j 有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别、日志要输出的地方和日志以何种形式输出。

综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

(3)当使用 Log4j 输出一条日志时,Log4j 自动通过不同的Appender(输出源)把同一条日志输出到不同的目的地。

例如:

console:输出到屏幕;file:输出到文件;socket:通过网络输出到远程计算机;jdbc:输出到数据库
在输出日志的过程中,通过Filter来过滤哪些log需要被输出,哪些log不需要被输出。在Loggers(记录器)组件中,级别分6种:TRACEDEBUGINFOWARNERRORFATAL。
这6个级别是有顺序的,TRACE<DEBUG < INFO < WARN < ERROR < FATAL,分别用来指定这条日志信息的重要程度,明白这一点很重要,Log4j有一个规则:只输出级别不低于设定级别的日志信息。
假设Loggers级别设定为INFO,则INFOWARNERRORFATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。
最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。

(4)log4j的应用:

《4.1》. 添加依赖

Log4j和Java标准库提供的日志不同,它是一个第三方提供的日志库,它是由Apache创建的日志框架。所以必须先添加依赖。

1.把从Apache官网下载。下载并解压后,将下面1个jar包加入项目的classpath中:

commons-logging-1.2.jar

我们需要从Apache官网下载Log4j,解压后,把以下3个jar包放到classpath中:

log4j-api-2.x.jarlog4j-core-2.x.jarlog4j-jcl-2.x.jar
《4.2》. 创建log4j配置
在输出日志的过程中,通过Filter来过滤哪些log需要被输出,哪些log不需要被输出。例如,仅输出ERROR级别的日志。最后,通过Layout来格式化日志信息,例如,自动添加日期、时间、方法名称等信息。上述结构虽然复杂,但我们在实际使用的时候,并不需要关心Log4j的API,而是通过配置文件来配置它。以XML配置为例,使用Log4j的时候,我们把一个log4j2.xml的文件放到classpath下就可以让Log4j读取配置文件并按照我们的配置来输出日志。

下面是一个配置文件的例子:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration><Properties><!-- 定义日志格式 --><Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %method %-5level%logger{36}%n%msg%n%n</Property><!-- 定义文件名变量 --><Property name="file.err.filename">log/err.log</Property><Property name="file.err.pattern">log/err.%i.log.gz</Property></Properties><!-- 定义Appender,即目的地 --><Appenders><!-- 定义输出到屏幕 --><Console name="console" target="SYSTEM_OUT"><!-- 日志格式引用上面定义的log.pattern --><PatternLayout pattern="${log.pattern}" /></Console><!-- 定义输出到文件,文件名引用上面定义的file.err.filename --><RollingFile name="err" bufferedIO="true"fileName="${file.err.filename}" filePattern="${file.err.pattern}"><PatternLayout pattern="${log.pattern}" /><Policies><!-- 根据文件大小自动切割日志 --><SizeBasedTriggeringPolicy size="1 MB" /></Policies><!-- 保留最近10份 --><DefaultRolloverStrategy max="10" /></RollingFile></Appenders><Loggers><Root level="info"><!-- 对info级别的日志,输出到console --><AppenderRef ref="console" level="info" /><!-- 对error级别的日志,输出到err,即上面定义的RollingFile --><AppenderRef ref="err" level="info" /></Root></Loggers>
</Configuration>
《4.3》log4j的应用:
4.3.1:对象创建
Log log = LogFactory.getLog(类名.class);使用logfactory实例化log对象LogFactory.getLog(getClass())此方式的优点为子类可直接使用该log对象

4.3.2:使用对象名.级别打印不同级别的输出信息,例:

log.info(“info”),输出打印info级别的信息


http://www.mrgr.cn/news/14296.html

相关文章:

  • Java的内存管理机制
  • OpenCV 图像处理基础算法介绍c++
  • USB端点
  • 云服务器在媒体处理中的应用有哪些
  • zsh 添加 用户@主机 路径显示
  • 遍历结果的推导
  • 迷雾大陆攻略:VMOS云手机流派辅助和技能加持助力!
  • 什么是云原生?
  • 易企秀Html5场景秀系统源码 海量模版可以选择 带源代码包以及搭建部署教程
  • python------python解释器,pycharm下载配置
  • 基于SpringBoot的在线答疑系统
  • 【系统分析师】-缓存
  • Spring概述
  • vue3 element-plus el-table 多层级表头动态渲染。
  • Android 12系统源码_输入系统(二)InputManagerService服务
  • C++领进门(第三讲)
  • Kubernetes与Docker的关系讲解
  • Quartz定时任务框架——若依
  • 基于vue框架的博物馆预约网站的设计与实现8k352(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
  • 大模型企业应用落地系列五》基于大模型的对话式推荐系统》大模型管理层