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. Selective Kernel Networks

    摘要:在标准的卷积神经网络(CNNs)中,每一层的人工神经元的感受野被设计成具有相同的大小.众所周知,视觉皮层神经元的感受野大小受刺激的调节,但在构建cnn时却很少考虑到这一点.我们在神经网络中提出了 ...

  2. 在H5页面播放m3u8音频文件

    需要使用hls插件 首先安装依赖npm install hls.js --save <audio ref="audio"></audio> import H ...

  3. Python使用websocket调用语音识别,语音转文字

    @ 目录 0. 太长不看系列,直接使用 1. Python调用标贝科技语音识别websocket接口,实现语音转文字 1.1 环境准备: 1.2 获取权限 1.2.1 登录 1.2.2 创建新应用 1 ...

  4. 循序渐进BootstrapVue,开发公司门户网站(3)--- 结合邮件发送,收集用户反馈信息

    在我们公司门户网站里面,如果有需要,我们可以提供一个页面给用户反馈信息,以便获得宝贵的用户信息反馈或者一些产品咨询的记录,一般这个结合邮件发送到负责人的邮箱即可.本篇随笔结合后端发送邮件的操作,把相关 ...

  5. Unity中的.Meta文件

    .meta文件是用于辅助管理Unity资源文件的文件,删除后,Unity会自动生成,里面记录了各个资源Inspector的信息,属性等等,Unity是不会改变源资源文件的,没有意义,它是靠.meta文 ...

  6. CentOS8安装GNOME3桌面并设置开机启动图形界面

    本篇文章介绍如何在CentOS8 Linux操作系统中安装GNOME3桌面环境和GDM(GNOME Display Manager)现实环境管理器. 环境 CentOS8 Minimal 安装GNOM ...

  7. Docker+Vagrant+Gitlab 构建自动化的 CI/CD

    如果你的开发流程是下面这个样子的, 那么你一定很好奇, 为什么我提交到仓库的代码可以自动部署并访问到最新的提交内容 这就是近年来兴起的 DevOps 文化, 很方便的解决了开发人员和运维人员每次发布版 ...

  8. CentOS-GitLab迁移(yum至Docker)

    yum备份迁移Docker版的GitLab 注:确保版本一致 1.yum备份 $ gitlab-rake gitlab:backup:create 2.执行完成后,在/var/opt/gitlab/b ...

  9. 暑假自学java第六天

    1,方法的覆盖:当子类继承父类,而子类中的方法与父类中方法的名称,返回类型及参数都完全一致时,就称子类中的方法覆盖了父类中的方法,有时也称方法的"重写" [不需要关键字] 2,th ...

  10. Vue:node.js与vue安装配置

    下载node.js 官网: https://nodejs.org/zh-cn/ 查看node版本 node -v 配置淘宝NPM镜像源(下载速度快) npm install -g cnpm --reg ...