异常处理
定义:异常是程序在“编译”或者“执行”的过程中可能出现的问题,注意:语法错误不算在异常体系中
为什么学习异常?
异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止
研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性
异常体系

Error:系统级别问题、JVM退出等,代码无法控制
Exception:java.lang包下,称为异常类,它表示程序本身可以处理的问题
RuntimeException及其子类:运行时异常,编译阶段不会报错。 (空指针异常,数组索引越界异常)
除RuntimeException之外所有的异常:编译时异常,编译期必须处理的,否则程序不能通过编译。 (日期格式化异常)。
编译时异常和运行时异常

简单来说:编译时异常就是在编译的时候出现的异常,运行时异常就是在运行时出现的异常。
运行时异常示例
数组索引越界异常: ArrayIndexOutOfBoundsException
空指针异常 : NullPointerException,直接输出没有问题,但是调用空指针的变量的功能就会报错。
数学操作异常:ArithmeticException
类型转换异常:ClassCastException
数字转换异常: NumberFormatException
编译时异常:是担心程序员的技术不行,在编译阶段就爆出一个错误, 目的在于提醒不要出错
// 编译时异常示例,使用parse时会出现日期解析异常:ParseException
String date = "2015-01-12 10:23:21";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(date);
System.out.println(d);
异常的默认处理流程
①默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException
②异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机
③虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据
④直接从当前执行的异常点干掉当前程序
⑤后续代码没有机会执行了,因为程序已经死亡
编译时异常的处理形式有三种:
出现异常直接抛出去给调用者,调用者也继续抛出去
出现异常自己捕获处理,不麻烦别人
前两者结合,出现异常直接抛出去给调用者,调用者捕获处理
异常处理方式1——throws
throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理
这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡
异常处理方式2——try…catch…
监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。
这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行
// 建议格式
try{
// 可能出现异常的代码!
}catch (Exception e){
e.printStackTrace(); // 直接打印异常栈信息
}
异常处理方式3——前两者结合
方法直接将异通过throws抛出去给调用者,调用者收到异常后直接捕获处理
在开发中按照规范来说第三种方式是最好的:底层的异常抛出去给最外层,最外层集中捕获处理
运行时异常的处理形式
- 运行时异常编译阶段不会出错,是运行时才可能出错的,所以编译阶段不处理也可以
- 按照规范建议还是处理:建议在最外层调用处集中捕获处理即可
自定义异常
Java无法为这个世界上全部的问题提供异常类。
如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类了
自定义异常的好处:
可以使用异常的机制管理业务问题,如提醒程序员注意。
同时一旦出现bug,可以用异常的形式清晰的指出出错的地方
注意:
- throw:在方法内部直接创建一个异常对象,并从此点抛出
- throws:用在方法申明上的,抛出方法内部的异常
自定义编译时异常
定义一个异常类继承Exception,重写构造器
在出现异常的地方用throw new 自定义对象抛出
作用:编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理!!
自定义运行时异常
定义一个异常类继承RuntimeException,重写构造器
在出现异常的地方用throw new 自定义对象抛出
作用:提醒不强烈,编译阶段不报错!!运行时才可能出现!!
日志框架
日志:用来记录程序运行过程中的信息,并可以永久进行存储。
日志技术具备的优势
可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)
可以随时以开关的形式控制是日志的记录和取消,无需侵入到源代码中去进行修改
体系结构

日志接口:一些规范,提供给日志的实现框架设计的标准。
日志框架:牛人或者第三方公司已经做好的实现代码,后来者直接可以拿去使用
因为对Commons Logging接口不满意,有人就搞了SLF4J。因为对Log4j的性能不满意,有人就搞了Logback
Logback日志框架
- Logback是基于slf4j的日志规范实现的框架,它是由log4j创始人设计的另一个开源日志组件,性能要比log4j要好
- 官方网站:
https://logback.qos.ch/index.html
Logback主要分为三个技术模块:
logback-core: 该模块为其他两个模块提供基础代码,必须有
logback-classic:完整实现了slf4j API的模块,必须有
logback-access 模块与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能
注意:想使用Logback日志框架,至少需要在项目中整合三个模块:slf4j-api、logback-core、logback-classic
Logback日志框架实现步骤:
①:导入Logback框架到项目中去。在项目下新建文件夹lib,导入Logback的jar包到该文件夹下

②:将存放jar文件的lib文件夹添加到项目依赖库中去。
③:将Logback的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)。
④:创建Logback框架提供的Logger日志对象,后续使用其方法记录系统的日志信息。public static final Logger LOGGER = LoggerFactory.getLogger(“类名");
Logback配置详解
Logback日志输出位置、格式设置:
通过logback.xml 中的<append>标签可以设置输出位置。
通常可以设置2个日志输出位置:一个是控制台、一个是系统文件中
输出到控制台的配置标志
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
输出到系统文件的配置标志
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
日志级别
ALL 和 OFF分别是打开、及关闭全部日志信息。
除此之外,日志级别还有: TRACE < DEBUG < INFO < WARN < ERROR ; 默认级别是DEBUG,对应其方法
作用:当在logback.xml文件中设置了某种日志级别后,系统将只输出当前级别,以及高于当前级别的日志
具体在<root level=”INFO”>标签的level属性中设置指定系统的日志级别