异常
- java的异常体系
- 一般通过
try{...} catch{...}
捕获异常 - 必须捕获的异常:Exception及其子类,但不包括RuntimeException及其子类
- 注意区分错误与异常,Error是无需捕获的严重错误,Exception是可以捕获的可处理错误
package Hello;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class Main {
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (UnsupportedEncodingException e) { // 注意catch的顺序,子类必须在前面
System.out.println("Bad encoding");
} catch (IOException e) {
System.out.println("IO Error");
} finally { // 可选
System.out.println("End"); // 在最后且必须执行
}
}
}
- 通过
throws
抛出异常只是推迟了异常的处理 main()
是最后捕获异常的机会,如果异常最终没有被捕获处理,就会报错!
try {
process1();
process2();
process3();
} catch (IOException | NumberFormatException e) {// 异常的处理逻辑相同,不存在继承关系
System.out.println("Bad Input");
} finally {
System.out.println("End");
}
- 通过方法调用栈可以追踪异常传播信息
public class Main {
public static void main(String[] args) {
process1();
}
static void process1() {
try {
process2();
} catch (Exception e) {
e.printStackTrace(); // 方法调用栈,追踪异常
} finally {
System.out.println("END");
}
}
static void process2() {
process3();
}
static void process3() {
Integer.parseInt(null);// 会抛出异常
}
如果有finally字句抛出异常,则catch中抛出的异常会被屏蔽
也可以将finally新抛出的异常添加到原有异常中,使用addSupressed()
方法
- 自定义异常
public class BaseException extends RuntimeException {
// 自定义异常应该从合适的Exception派生,推荐RuntimeException
public BaseException() {
}
// 自定义异常应该定义多个构造方法
public BaseException(String message) {
super(message);
}
// 构造方法可以借助IDE工具生成(Generate)
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(Throwable cause) {
super(cause);
}
}
public class Main {
public static void main(String[] args) {
try {
process1();
} catch (BaseException e) {
System.out.println(e.toString());
// throw new BaseException("错误信息!")
} catch (Exception e) {
//
}
}
}
自定义异常的构造方法通常使用父类的构造方法即可,输出错误信息等!
断言
- 是一种程序调试方式,使用
assert
关键字,条件预期为true - 如果断言失败,抛出
AssertionError
,程序结束退出 - Java默认关闭断言指令,可以给虚拟机传递
-ea
参数启用断言
public class Main {
public static void main(String[] args) {
double x = Math.abs(-123);
assert x < 0 : "x must a positive number";
System.out.println(x);
}
}
在IDE的Edit Configuration里面的VM options中加入参数
-ea:类名的完整路径
才会执行assert语句
一般只在调试和开发阶段使用断言
日志
- 日志是为了替代System.out.println(),可以定义格式、重定向到文件等
- 日志可以存档,便于追踪问题
- 日志记录按级别分类
- 可以根据配置文件调整日志,JDK提供了Logging:java.util.logging
日志级别 | 描述 |
---|---|
OFF | 关闭:最高级别,不输出日志 |
FATAL | 致命:输出非常严重的可能会导致应用程序终止的错误 |
ERROR | 错误:输出错误,但应用还能继续运行 |
WARN | 警告:输出可能潜在的危险状况 |
INFO | 信息:输出应用运行过程的详细信息(默认级别) |
DEBUG | 调试:输出更细致的对调试应用有用的信息 |
TRACE | 跟踪:输出更细致的程序运行轨迹 |
ALL | 所有:输出所有级别信息 |
- 我们较常用的是Commons Logging
- Apache创建的日志模块
- 可以挂接不同的日志系统
- 自动搜索并使用Log4j
- 我们需要下载jar包放在lib库中,然后再IDEA的【File–>Project Structure–>Modules–>Dependencies】导入
public class Main {
// Log
static final Log log = LogFactory.getLog(Main.class);
public static void main(String[] args) {
log.info("输出Info信息");
try {
new Person();
} catch (Exception e) {
log.error("Exception",e);
}
}
}
建议在src的同级目录建立lib库,将我们引用的jar包放入
- Log4j
通过Commons Logging实现日志,不需要修改任何代码即可使用Log4j;(系统自动检测到)
只需把log4j2.xml和相关jar加入classpath即可;
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。这些可以通过.xml配置文件来灵活地进行配置,而不需要修改应用的代码。
- Logback
- Logback 的架构非常的通用,适用不同的使用场景,它比其它所有的日志系统更快并且更小,包含了许多独特并且有用的特性,逐步取代了Log4j。
- 在应用程序中,合理的打日志会让监测项目更加轻松!
- 可以查看logback中文网了解一下
结语
这部分主要学习了Java中异常处理和调试的工具,后面有新的学习体会再做分享!