Java核心技术(第8版) – 读书笔记 – 第11章

本章讨论的内容:异常、断言、日志。

1、错误分类:
(1)用户输入错误:输入url不合法
(2)设备错误:打印机被关掉了
(3)物理限制:如磁盘满了
(4)代码错误:下标越界等

2、有的时候出错用返回码表示,如false,java.io中常用的-1表示EOF等。但更多的时候,这些信息不足以表示错误类型。异常(Exception)更为常用。

3、Java中的所有可抛出错误和异常继承自Throwable,分为两类:
(1)Error:不可恢复的错误,如OutOfMemoryError,它们不应该由用户主动抛出。一般发生这些错误的时候,就应该结束程序了。
(2)Exception:可恢复或者处理的异常。

4、Exception又分为两类:
(1)RuntimeException:类型转换出错、URL格式错误、加载不存在的Class等。这些都应该是在程序设计中进行避免或主动判断的。
(2)IOException:I/O错误导致的。

5、如果类的某个方法内显示的throw出了某个Excpeton,则应该在方法定义的时候,声明”检查异常“,比如FileInputStream的构造函数:

它将构造一个FileInputStream对象,但有可能抛出一个FileNotFoundException异常。对于继承自RuntimeException的异常,不应该写在throws里,而是应该在代码中避免的。比如ArrayIndexOutOfBoundsException,也不应该写Error继承的类。

6、如果调用一个声明”检查异常“的方法,则要么在自己的方法上throws它,要么内部处理它。

7、如何在代码中抛出异常:

8、有时候,Java内置的异常体系不能满足你的需求,可以实现自己的异常类:

上面的super(msg),会把msg存在Throwable中,通过getMessage()方法可以返回这个msg。

然后,就可以抛出自己的异常了:

9、捕获异常:

如果try块内抛出了异常,将直接执行catch块中的内容。
如果try内没有抛出异常,将跳过catch块。

10、在定义基础逻辑时,最好不在内部处理异常,而直接定义throws,将异常交给调用者处理。

11、编译器将严格检查throws说明,如果调用了一个抛出异常的方法,就必须要么对它进行处理(try/catch),要么把它传递出去。

12、如果覆盖一个超类方法,那么子类的throws不许出现超过超类所列出的异常范围。也就是说,需要在子类内部处理所有超类没有列出throws的异常。

13、捕获多个异常:

14、获取异常信息:

15、有时候,在catch块内,可以还会抛出异常,即补上异常更详细的信息,方便调用这查看。有一种不太损失调用信息的好方法,如下:

恢复时候,用如下方法:

16、finally放在catch后,不管是否进入了catch,都会执行finally。适用于资源的释放(文件句柄,数据库链接等)。有时候,.close()会抛出异常,要注意处理。例如InputStream。

17、堆栈跟踪是很有用的技术,可以分析程序执行的流程,调试时候非常有用:

下面是一个打印堆栈跟踪信息的例子:

打印出来的结果:

18、JDK5之后,为线程Thread增加了静态的getAllStackTraces(),可以对所有线程进行跟踪。

19、对异常的建议:
(1)不要用异常代替简单判断,因为异常处理会消耗大量性能。
(2)不要过分细化异常处理,可以将多个异常放在一个try块内,附加多个catch即可。
(3)传递异常不可耻,在必要时候应当使用。

20、JDK1.4后开始支持断言,用于程序调试时的诊断,格式:

当条件为false时,抛出AssertionError异常。

21、断言可以在java命令行被禁用:

22、断言用法:
(1)断言是致命、不可恢复的错误
(2)断言只用于开发和调试阶段

23、使用日志的优势:
(1)在发布阶段,可以很容易的取消调试日志(按照级别分类)
(2)可以记录到更多的文件格式,如XML、纯文本、数据库等。

24、默认的日志管理器,可以与System.out互换:

25、自创建日志管理器:

26、日志级别:
(1)SEVERE
(2)WARNING
(3)INFO
(4)CONFIG
(5)FINE
(6)FINER
(7)FINEST
Level.OFF可以关闭所有级别的日志。
默认日志管理器是INFO及以上

27、记录日志的方法:

28、默认的日志管理只记录了类和方法名,没法具体到行,例如:

29、Logger可以直接用于记录日志:

30、可以通过修改java命令行或者JVM配置来更改默认的日志级别,以我的Ubuntu为例,在:

/usr/lib/jvm/java-6-sun/jre/lib/logging.properties里面,里面部分内容:

31、命令行方式改变默认日志级别:

32、我们在刚才的例子中已经看到,一部分日志已经是国际化的了(如显示”信息:“而不是INFO:)。

我们对于输出的msg也可以进行国际化:比如对于中文用户提示”用户名“,对英文提示”username”。

一个程序可以包含多个语种的资源包,用ResourceBundle类对它们自动定位,这一般按照类名完成。

绑定资源包要用两个String参数的工厂方法函数:

例如,新建如下文件com/TestLogger_en.properties,这是英文的国际化,内容如下:

对于中文资源文件com/TestLogger_zh_CN.properties,如下:

记录日志时,可以用附加Object[]的方法将{0}这些占位符替换掉。

例子,注意注释:

33、日志处理器(Log Handler):如果说日志级别决定了是否输出,那么日志处理器决定了输出到哪里。默认的ConsoleHandler是类似System.out,输出到屏幕。

其他常用的Handler还有:
java.util.logging.FileHandler  // 输出到文件

更详细的配置一般是设置logging.properties,具体的可以参考网上的文章。

34、过滤器,也可以自己实现过滤器Filter接口,决定哪些日志可以被写入,哪些直接丢弃了。

35、格式化器,类似于Log4j中的格式化器,但在默认的java.util.logging中要自己实现Formatter接口,并添加到Logger中。

36、日志其他注意事项:
(1) 最好同一个应用共用一个日志,private static final Logger logger = Logger.getLogger(……);
(2) 默认的这个日志很难用,玩玩还凑合,正规系统建议还是log4j吧……

37、常用调试技术
(1)System.out / System.err 结合shell管道等打印到文件
(2)Logger
(3)IDE
(4)借助外界程序(一般是性能分析)

38、想观察执行Java过程时的类加载过程,则加入-verbose:

39、JDK5后支持lint,即编译静态检查,在javac时候加上-Xlint:all即可:

40、JDK5后可以用jconsole processID观察性能变化。当然现在一般借助更为专业的商业化第三方软件。

41、java.awt.Robot可以移动鼠标、模拟点击、模拟键盘事件,还可以截屏幕。书中介绍这个是说可以模拟用户进行测试,有点扯吧,截屏功能倒还是实用。

42、java也支持调试。。

一般这个是IDE完成的,调试单步什么的还是Ecelipse等IDE吧。

本章完。

2 thoughts on “Java核心技术(第8版) – 读书笔记 – 第11章

  1. coder4vanxining

    请问博主是怎么记下这些读书笔记的呢?是看电子版还是实体书?假如是后者,那么很佩服楼主啊~

    Reply
    1. coder4coder4 Post author

      看扫描的电子版,所以和纸质差不多,没法复制。都是手敲进去的,过过脑子才能记住啊,呵呵。

      Reply

Leave a Reply

Your email address will not be published.