【阅读笔记】Java核心技术卷一 #5.Chapter7
7 异常、断言和日志
在 Java 中,如果某个方法不能够采用正常的途径完整它的任务,就可以通过另外一个路径退出方法。
在这种情况下,将会立刻退出,并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。
此外,调用这个方法的代码也将无法继续执行,取而代之的是异常处理机制开始搜索能够处理这种异常状况的异常处理器。
7.1 处理错误
所有的异常都是由 Throwable 继承而来,并分为两个分支:Error和Exception。
Error 类继承链描述了 Java 运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。这种情况很少出现。
Exception 继承链分为两个分支:由程序错误导致的异常属于RuntimeException;
而程序本身没有问题,但由于像 I/O 错误这类问题导致的异常属于其他异常。
Java 语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查(unchecked)异常,所有其他的异常称为受查(checked)异常。
编译器将核查是否为所有的受査异常提供了异常处理器。
一个方法必须声明所有可能抛出的受查异常 ,而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)。
如果方法没有声明所有可能发生的受查异常,编译器就会发出一个错误消息。
如果在子类中覆盖了超类的一个方法,子类方法中声明的受查异常不能比超类方法中声明的异常更通用。
如果超类方法没有抛出任何受查异常,子类也不能抛出任何受查异常。
7.2 捕获异常
7.2.1 捕获一个异常
- try / catch 处理
- throws 传递出去
7.2.2 捕获多个异常
try {
code that might throw exceptions
}
catch (FileNotFoundException e) {
emergency action for missing files
}
catch (UnknownHostException e) {
emergency action for unknown hosts
}
catch (IOException e) {
emergency action for all other I/O problems
}
/// 第一个异常变量 e 隐含为 final 变量
try {
code that might throw exceptions
}
catch (FileNotFoundException | UnknownHostException e) {
emergency action for missing files and unknown hosts
}
catch (IOException e) {
emergency action for all other I/O problems
}
7.2.3 再次抛出异常与异常链
可以在 catch 里再抛出异常,这样做的目的是改变异常的类型:
try {
access the database
}
catch (SQLException e) {
throw new ServletException("database error: " + e.getMessage());
}
更好的处理办法是将原始异常设置为新异常的“原因”:
try {
access the database
}
catch (SQLException e) {
Throwable se = new ServletException("database error");
se.initCause(e);
throw se;
}
// 这样一来,可以使用下面这条语句重新得到原始异常:
Throwable e = se.getCause()
7.2.4 finally 子句
try 语句可以只有 finally 子句,而没有 catch 子句。
finally 执行的几种情况
try/catch 和 try/finally 解耦合。里面的 try 语句块只确保输入流被关闭;
外面的 try 语句块只确保报告出现的错误;同时也会报告 finally 子句中出现的错误。
InputStream in = . . .;
try {
try {
code that might throw exceptions
}
finally {
in.close();
}
}
catch (IOException e) {
show error message
}
7.2.5 带资源的 try 子句
try (Scanner in = new Scanner(new FileInputStream("/usr/share/dict/words"), "UTF-8");
PrintWriter out = new PrintWriter("out.txt"))
{
while (in.hasNext())
out.println(in.next().toUpperCase());
}
不论这个块如何退出,in 和 out 都会关闭,就好像使用了 finally 块一样。
之前,如果 try 块抛出一个异常,而且 close 方法也抛出一个异常,这就会带来一个难题。带资源的 try 语句可以很好地处理这种情况。
原来的异常会重新抛出,而 close 方法抛出的异常会“被抑制”。这些异常将自动捕获,并由 addSuppressed 方法增加到原来的异常。
如果对这些异常感兴趣,可以调用 getSuppressed 方法,它会得到从 close 方法抛出并被抑制的异常列表。
7.2.6 分析堆栈轨迹元素
堆栈轨迹(stack trace)是一个方法调用过程的列表,它包含了程序执行过程中方法调用
的特定位置。
Throwable t = new Throwable();
t.printStackTrace();
StackTraceElement[] frames = t.getStackTrace();
///
Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
for (Thread t : map.keySet())
{
StackTraceElement[] frames = map.get(t);
analyze frames
}
7.3 使用异常机制的tips(略)
7.4 使用断言(暂略)
7.5 记录日志
logging API 解决频繁插入/删除 System.out.println 的问题。
以下仅介绍简单使用:
// Logger log = Logger.getLogger("name");
Logger global = Logger.getGlobal();
global.info("this is a message");
global.setLevel(Level.OFF);
通常有7个日志级别:
SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST
每个级别有对应的记录方法:
logger.warning("message");
logger.fine("message");
...
logger.log(Level.WARNING, "message");
logger.log(Level.FINE, "message");
...
设置日志对象记录的级别。默认日志级别为 INFO,可以记录 INFO 与更高的两个级别的日志。
logger.setLevel(Level.FINE);
...
logger.setLevel(Level.ALL); //开启所有级别的记录
logger.setLevel(Level.OFF); //关闭所有级别的记录
更高级的日志使用暂略。常用日志框架有
Commons-logging、Slf4j和log4j等。
7.6 调试技巧(暂略)
这部分以后可能会补上
【阅读笔记】Java核心技术卷一 #5.Chapter7的更多相关文章
- 【阅读笔记】Java核心技术卷一 #0
这是一篇备忘性质的读书笔记,仅记录个人觉得有用的知识点 本文作为一个目录索引,部分章节跳过 吐槽:此书中文翻译有不少地方不太通顺,这种情况我要把英文版对应的部分也读一遍才能明白(说实话,英文里的从句表 ...
- java核心技术卷一
java核心技术卷一 java基础类型 整型 数据类型 字节数 取值范围 int 4 +_2^4*8-1 short 2 +_2^2*8-1 long 8 +_2^8*8-1 byte 1 -128- ...
- 对《Java核心技术卷一》读者的一些建议
<Java核心技术卷一>是唯一可以和<Java编程思想>媲美的一本 Java 入门书.单从技术的角度来看,前者更好一些.但上升到思想层面嘛,自然后者更好,两者的偏重点不同. 思 ...
- 读《java核心技术卷一》有感
过去一个多月了吧.才囫囵吞枣地把这书过了一遍.话说这书也够长的,一共706页.我从来不是个喜欢记录的人,一直以来看什么书都是看完了就扔一边去,可能有时候有那么一点想记录下来的冲动,但算算时间太紧,很多 ...
- 【阅读笔记】Java核心技术卷一 #6.Chapter8
8 泛型程序设计 8.1 为什么要使用泛型程序设计 类型参数(type parameters)(E.T.S...) 通配符类型(wildcard type)(?) 注意这两者用法用处并不同. 8.2 ...
- 【阅读笔记】Java核心技术卷一 #4.Chapter6
6 接口.lambda 表达式与内部类 6.1 接口 6.1.1 接口概念 接口绝不能含有实例域:但在接口中可以定义常量,被自动设为 public static final 接口中的所有方法自动地属于 ...
- 【阅读笔记】Java核心技术卷一 #3.Chapter5
5 继承 5.1 类.超类和子类 5.1.1 定义子类 超类(superclass)和子类(subclass), 基类(base class)和派生类(derived class), 父类(paren ...
- 【阅读笔记】Java核心技术卷一 #2.Chapter4
4 对象和类 4.1 面向对象程序设计概述(略) 4.2 使用预定义类 java.time.LocalDate static LocalDate now(); static LocalDate of( ...
- 【阅读笔记】Java核心技术卷一 #1.Chapter3
3 Java的基本程序设计结构 3.1 一个简单的 Java 应用程序(略) 3.2 注释(略) 3.3 数据类型 8种基本类型 byte,short,int,long float,double ch ...
随机推荐
- 基于TensorFlow的服装分类
1.导包 #导入TensorFlow和tf.keras import tensorflow as tf from tensorflow import keras # Helper libraries ...
- 卢卡斯定理&&中国剩余定理
卢卡斯定理(模数较小,且是质数) 式子C(m,n)=C(m/p,n/p)*C(m%p,n%p)%p 至于证明(我也不会QAQ,只要记住公式也该就好了). 同时卢卡斯定理一般用于组合数取模上 1.首先当 ...
- Java进阶 | Proxy动态代理机制详解
一.Jvm加载对象 在说Java动态代理之前,还是要说一下Jvm加载对象的过程,这个依旧是理解动态代理的基础性原理: Java类即源代码程序.java类型文件,经过编译器编译之后就被转换成字节代码.c ...
- npm ERR! Unexpected end of JSON input while parsing near '...'解决方法
npm install时出现npm err! Unexpected end of JSON input while parsing near'...'错误 输入 npm cache clean -- ...
- Terraform模块Module管理,聚合资源的抽取与复用
我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 最近工作中用到了Terraform,权当学习记录一下,希望能帮助到其它人. Terraform系列文章如下: T ...
- jenkins 修改端口后无法启动的解决思路
一.问题 jenkins网站绑定域名后直接通过域名访问使用的是8080端口,为方便用户访问因此须监听80端口,而为了安全起见linux一般不用root身份运行,综上,需要以普通用户来运行监听80端口时 ...
- 第11章:Pod数据持久化
参考文档:https://kubernetes.io/docs/concepts/storage/volumes/ Kubernetes中的Volume提供了在容器中挂载外部存储的能力 Pod需要设置 ...
- 第4章:kubectl命令行管理工具
kubectl --help 查看帮助信息 kubectl create --help 查看create命令帮助信息 命令 描述 create 通过文件名或标准输入创建资源 expose 将一个资源公 ...
- 5、基本数据类型(str)
5.1.字符串: 1.n1 = "lc" n2 = 'root' n3 = """chang""" n4='''tom' ...
- 部署JAX-WS Web服务作为战争中的Apache Tomcat(Deploying JAX-WS webservice as War in Apache Tomcat)
问 题 I have developed a webservice using JAXWS and able to run it from the eclipse on Tomcat 7 with ...