7 异常、断言和日志

在 Java 中,如果某个方法不能够采用正常的途径完整它的任务,就可以通过另外一个路径退出方法。

在这种情况下,将会立刻退出,并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。

此外,调用这个方法的代码也将无法继续执行,取而代之的是异常处理机制开始搜索能够处理这种异常状况的异常处理器。

7.1 处理错误

所有的异常都是由 Throwable 继承而来,并分为两个分支:ErrorException

Error 类继承链描述了 Java 运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。这种情况很少出现。

Exception 继承链分为两个分支:由程序错误导致的异常属于RuntimeException

而程序本身没有问题,但由于像 I/O 错误这类问题导致的异常属于其他异常

Java 语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查(unchecked)异常,所有其他的异常称为受查(checked)异常。

编译器将核查是否为所有的受査异常提供了异常处理器。

一个方法必须声明所有可能抛出的受查异常 ,而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)。

如果方法没有声明所有可能发生的受查异常,编译器就会发出一个错误消息。

如果在子类中覆盖了超类的一个方法,子类方法中声明的受查异常不能比超类方法中声明的异常更通用。

如果超类方法没有抛出任何受查异常,子类也不能抛出任何受查异常。

7.2 捕获异常

7.2.1 捕获一个异常

  1. try / catch 处理
  2. 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-loggingSlf4jlog4j等。

7.6 调试技巧(暂略)

这部分以后可能会补上

【阅读笔记】Java核心技术卷一 #5.Chapter7的更多相关文章

  1. 【阅读笔记】Java核心技术卷一 #0

    这是一篇备忘性质的读书笔记,仅记录个人觉得有用的知识点 本文作为一个目录索引,部分章节跳过 吐槽:此书中文翻译有不少地方不太通顺,这种情况我要把英文版对应的部分也读一遍才能明白(说实话,英文里的从句表 ...

  2. java核心技术卷一

    java核心技术卷一 java基础类型 整型 数据类型 字节数 取值范围 int 4 +_2^4*8-1 short 2 +_2^2*8-1 long 8 +_2^8*8-1 byte 1 -128- ...

  3. 对《Java核心技术卷一》读者的一些建议

    <Java核心技术卷一>是唯一可以和<Java编程思想>媲美的一本 Java 入门书.单从技术的角度来看,前者更好一些.但上升到思想层面嘛,自然后者更好,两者的偏重点不同. 思 ...

  4. 读《java核心技术卷一》有感

    过去一个多月了吧.才囫囵吞枣地把这书过了一遍.话说这书也够长的,一共706页.我从来不是个喜欢记录的人,一直以来看什么书都是看完了就扔一边去,可能有时候有那么一点想记录下来的冲动,但算算时间太紧,很多 ...

  5. 【阅读笔记】Java核心技术卷一 #6.Chapter8

    8 泛型程序设计 8.1 为什么要使用泛型程序设计 类型参数(type parameters)(E.T.S...) 通配符类型(wildcard type)(?) 注意这两者用法用处并不同. 8.2 ...

  6. 【阅读笔记】Java核心技术卷一 #4.Chapter6

    6 接口.lambda 表达式与内部类 6.1 接口 6.1.1 接口概念 接口绝不能含有实例域:但在接口中可以定义常量,被自动设为 public static final 接口中的所有方法自动地属于 ...

  7. 【阅读笔记】Java核心技术卷一 #3.Chapter5

    5 继承 5.1 类.超类和子类 5.1.1 定义子类 超类(superclass)和子类(subclass), 基类(base class)和派生类(derived class), 父类(paren ...

  8. 【阅读笔记】Java核心技术卷一 #2.Chapter4

    4 对象和类 4.1 面向对象程序设计概述(略) 4.2 使用预定义类 java.time.LocalDate static LocalDate now(); static LocalDate of( ...

  9. 【阅读笔记】Java核心技术卷一 #1.Chapter3

    3 Java的基本程序设计结构 3.1 一个简单的 Java 应用程序(略) 3.2 注释(略) 3.3 数据类型 8种基本类型 byte,short,int,long float,double ch ...

随机推荐

  1. 代码生成器:IDEA 强大的 Live Templates

    前言 Java 开发过程经常需要编写有固定格式的代码,例如说声明一个私有变量,logger或者bean等等.对于这种小范围的代码生成,我们可以利用 IDEA 提供的 Live Templates功能. ...

  2. 入“坑”mybatis后如何挣脱?

    既然已经入"坑"mybatis了,你竟然还想着挣脱,我是不会让你挣脱的~ 当然我有一个算是挣脱的办法.那就是把它学会.理解透.这样我们也就不用在坑里一直徘徊,也算得上是一种挣脱吧! ...

  3. Linux中cut,sort,uniq和wc的用法

    一.cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对"行"来进行分析的,并不是整篇信息分析的.1.语法格式为:cut [-bn] [fil ...

  4. 组建Redis集群遇到`GLIBC_2.14' not found和ps -ef 不显示用户名

    RHEL6.9组建Redis sentinel集群遇到两个问题 今天在组件Redis sentinel 集群时,遇到两个问题,之前已经组建多次,都没碰到类似问题,在解决这两个问题时,耗费些时间. 问题 ...

  5. POJ 1410 判断线段与矩形交点或在矩形内

    这个题目要注意的是:给出的矩形坐标不一定是按照左上,右下这个顺序的 #include <iostream> #include <cstdio> #include <cst ...

  6. codeforces 830E dp

    大致题意: n场比赛,k个钱币.赢一场获得一个钱币,输一场失去一个钱币,一旦钱币数量为2k个或者0个,就马上离开比赛.给出n个长度字符串,由W,D,L,?四个字符组成,W表示赢,L表示输,D表示平局, ...

  7. 闲聊,Python中的turtle

    写在前面 其实我也不知道为什么我会写这个,本文涉及信号与传递,Python 正题 近期看到一个3年前的视频,1000个圆一笔画出一个Miku 在观看完源码了以后,我发现这是这调用的是基本的goto,用 ...

  8. WebContent的子目录里面的jsp文件无法将数据传递给Servlet

    在WebContent下创建子目录FormCheck,register.jsp将跳转到RegisterServlet这个Servlet中去 分两种情况:在web.xml里面配置 和 使用注解 1.在w ...

  9. Adaptive AUTOSAR 学习笔记 3 - AP 背景、技术及特征(中文翻译)

    本系列学习笔记基于 AUTOSAR Adaptive Platform 官方文档 R20-11 版本.本文从AUTOSAR_EXP_PlatformDesign.pdf开始,一边学习,一边顺带着翻译一 ...

  10. postgresql行列转换

    --安装扩展 CREATE EXTENSION tablefunc --使用CROSSTAB函数 SELECT * FROM CROSSTAB('SELECT 主键, 需转换的列名, 需转换的列值 F ...