Java Review三十三、异常处理----补充:断言、日志、调试

@



使用断言

断言(Assertion)是一种调试程序的方式。在Java中,使用assert关键字来实现断言。

断言的概念

假设确信某个属性符合要求, 并且代码的执行依赖于这个属性。例如, 需要计算:

double y = Math.sqrt(x);

确信,这里的 X 是一个非负数值。原因是:X 是另外一个计算的结果,而这个结果不可能是负值;或者 X 是一个方法的参数,而这个方法要求它的调用者只能提供一个正整数。
当然还应当进行检查, 以避免让“ 不是一个数” 的数值参与计算操作。

可以抛出一个异常:

if (x < 0) throw new 111egalArgumentException("x < 0");

但是这段代码会一直保留在程序中, 即使测试完毕也不会自动地删除。如果在程序中含有大量的这种检查,程序运行起来会相当慢。

断言机制允许在测试期间向代码中插入一些检査语句。当代码发布时,这些插人的检测语句将会被自动地移走。

Java 语言引人了关键字 assert。这个关键字有两种形式:

assert 条件;
assert 条件:表达式;

这两种形式都会对条件进行检测, 如果结果为 false,则抛出一个 AssertionError 异常。

在第二种形式中,表达式将被传人 AssertionError 的构造器, 并转换成一个消息字符串。

启用和禁用断言

在默认情况下, 断言被禁用。可以在运行程序时用 -enableassertions 或 -ea 选项启用:

java -enableassertions MyApp

需要注意的是, 在启用或禁用断言时不必重新编译程序。启用或禁用断言是类加载器( class loader) 的功能。当断言被禁用时, 类加载器将跳过断言代码, 因此,不会降低程序运行的速度。

也可以在某个类或整个包中使用断言, 例如:

java -ea:MyClass -eaiconi.inycompany.inylib..,MyApp

这条命令将开启 MyClass 类以及在 com.mycompany.mylib 包和它的子包中的所有类的断言。选项 -ea 将开启默认包中的所有类的断言。

也可以用选项 -disableassertions 或 -da 禁用某个特定类和包的断言:

ava -ea:... -da:MyClass MyApp

日志

每个 Java 程序员都很熟悉在有问题的代码中插入一些 System.out.println 方法调用来帮助观察程序运行的操作过程。 当然, 一旦发现问题的根源, 就要将这些语句从代码中删去。如果接下来又出现了问题, 就需要再插入几个调用 System.out.println方法的语句。

记录日志API 就是为了解决这个问题而设计的。

下面先讨论这些 API 的优点。

  • 可以很容易地取消全部日志记录,或者仅仅取消某个级别的日志,而且打开和关闭这个操作也很容易。
  • 可以很简单地禁止日志记录的输出, 因此,将这些日志代码留在程序中的开销很小。
  • 日志记录可以被定向到不同的处理器, 用于在控制台中显示, 用于存储在文件中等。
  • 日志记录器和处理器都可以对记录进行过滤。过滤器可以根据过滤实现器制定的标准丢弃那些无用的记录项。
  • 日志记录可以采用不同的方式格式化,例如,纯文本或 XML。
  • 应用程序可以使用多个日志记录器, 它们使用类似包名的这种具有层次结构的名字,例如, com.mycompany.myapp0 •在默认情况下,日志系统的配置由配置文件控制。如果需要的话, 应用程序可以替换
    这个配置。

基本曰志

要生成简单的日志记录,可以使用全局日志记录器(global logger) 并调用其 info 方法:

Logger.getClobal 0,info("File->Open menu item selected");

在默认情况下,这条记录将会显示以下内容:

May 10,2013 10:12:15 PM LogginglmageViewer fileOpen
INFO: File->0pen menu item selected

但是, 如果在适当的地方(如 main 开始)调用

Logger.getClobal ().setLevel (Level .OFF);

将会取消所有的日志。

API:java.util.logging

高级曰志

从前面已经看到“ 虚拟日志”,下面继续看一下企业级( industrial-strength) 日志。在一个专业的应用程序中,不要将所有的日志都记录到一个全局日志记录器中,而是可以自定义日志记录器。

可以调用 getLogger 方法创建或获取记录器:

private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp"):

与包名类似,日志记录器名也具有层次结构。事实上, 与包名相比,日志记录器的层次性更强。 对于包来说,一个包的名字与其父包的名字之间没有语义关系,但是日志记录器的父与子之间将共享某些属性。例如, 如果对 com.mycompany 日志记录器设置了日志级别,它的子记录器也会继承这个级别 。

通常, 有以下 7 个日志记录器级别:

  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST

在默认情况下,只记录前夂个级别。 也可以设置其他的级別。例如:

logger,setLevel (Level .FINE);

现在, FINE 和更高级别的记录都可以记录下来。
另外, 还可以使用 Level.ALL 开启所有级别的记录, 或者使用 Level.OFF 关闭所有级别的记录。
对于所有的级别有下面几种记录方法:

logger.warning(message):
logger,fine(message) ;

同时, 还可以使用 log 方法指定级别, 例如:

logger.log(Level .FINE,message);

日志记录说明

日志记录常用的操作:

  • 1 ) 为一个简单的应用程序, 选择一个日志记录器,并把日志记录器命名为与主应用程序包一样的名字,例如,com.mycompany.myprog。

可以通过调用下列方法得到日志记录器:

Logger logger = Logger.getLogger("com.mycompany.myprog");

为了方便,可以利用一些日志操作将下面的静态域添加到类中:

private static final Logger logger = Logger.getLogger("com.mycompany.nyprog"):
  • 2 ) 默认的日志配置将级别等于或高于 INFO 级别的所有消息记录到控制台。用户可以覆盖默认的配置文件。但是正如前面所述,改变配置需要做相当多的工作。因此,最好在应用程序中安装一个更加适宜的默认配置。

下列代码确保将所有的消息记录到应用程序特定的文件中。可以将这段代码放置在应用程序的 main方法中。

if (System,getProperty("java,util.logging.config.dass") == null
&& System.getPropertyC'java.util.logging.config.file") == null) {
try
{
   Logger.getLogger("").setLevel(Level.ALL);
   final int L0C_R0TATI0N_C0UNT = 10;
   Handler handler = new FileHandler('Wmyapp.log",L0G_R0TATI0N_C0UNT):
   Logger.getLogger("").addHandler(handler): }
catch (IOException e) {
  logger.log(Level.SEVERE,"Can't create log file handler",e); 
  }
  }
  • 3 ) 现在,可以记录自己想要的内容了。但需要注意:所有级别为 INFO、 WARNING 和SEVERE 的消息都将显示到控制台上。因此, 最好只将对程序用户有意义的消息设置为这几个级别。将程序员想要的日志记录,设定为 FINE 是一个很好的选择。

当调用 System.out.println 时, 实际上生成了下面的日志消息:

logger.fine("File open dialog canceled";

记录那些不可预料的异常也,例如:

try
{}
catch (SonreException e) {
   logger,log(Level.FINE,"explanation",e); 
  }

调试技巧

在Intellij IDEA中使用Debug
how2j.java:如何在Eclipse中调试Java程序
W3Cschool:jUnit教程
Spring Boot干货系列:(十二)Spring Boot使用单元测试



参考:
【1】:《Java核心技术 卷一》
【2】:廖雪峰的官方网站:使用断言
【3】:廖雪峰的官方网站:使用JDK Logging
【4】:廖雪峰的官方网站:使用Commons Logging
【5】:廖雪峰的官方网站:使用Log4j
【6】:廖雪峰的官方网站:使用SLF4J和Logback
【7】:how2j.java: Log4j系列教材

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


@ 注解能被用来为程序元素( 类、 方法、 成员变量等) 设置元数据。 值得指出的是, 注解不影响程序代码的执行, 无论增加、 删除注解, 代码都始终如一地执行。 如果希望让程序中的注解在运行时起一定
@ 1、线性表的概念 线性表是最常见也是最简单的一种数据结构。简言之, 线性表是n个数据元素的有限序列。 其一般描述为: A={a1,a2,……an) 一个数据元素通常包含多个数据项, 此时每个数据元
简介 ArrayList是开发中使用比较多的集合,它不是线程安全的,CopyOnWriteArrayList就是线程安全版本的ArrayList。CopyOnWriteArrayList同样是通过数组
在 Java String类源码阅读笔记 里学习了String类的源码,StringBuilder、StringBuffer是经常拿来和String类做对比的两个类,可谓是“爱恨纠缠” ,这里我们继续
话不多说,先上图。 1、基本概念 欲说线程,必先说进程。 进程:进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。 线程:线程是进程的一个执行路径,一个进程中至少有一个线程,进
@ 网络基础 计算机网络是指两台或更多的计算机组成的网络,在同一个网络中,任意两台计算机都可以直接通信,因为所有计算机都需要遵循同一种网络协议。 那什么是互联网呢?互联网是网络的网络(internet
JVM是面试中必问的部分,本文通过思维导图以面向面试的角度整理JVM中不可不知的知识。 先上图: 1、JVM基本概念 1.1、JVM是什么 JVM 的全称是 「Java Virtual Machine
@ 本文基于jdk1.8 HashMap采用 key/value 存储结构,每个key对应唯一的value。 在jdk1.7之前,HashMap 的内部存储结构是数组+链表。 在jdk1.8中 Has
@ Eclipse是很多Java开发者的第一个开发工具,尽管开源的Eclipse在一后起之秀的对比下,显得有些颓势,但是,Eclipse有着丰富的插件支持。选择合适的插件,Eclipse表示:老夫也能
@ 准备 LinkedList是基于双向链表数据结构实现的Java集合(jdk1.8以前基于双向循环链表),在阅读源码之前,有必要简单了解一下链表。 先了解一下链表的概念:链表是由一系列非连续的节点组
@ 写博客哪有刷逼乎有意思 1 写博客哪有刷逼乎有意思 2 写博客哪有刷逼乎有意思 3 类的加载、 连接和初始化 系统可能在第一次使用某个类时加载该类, 也可能采用预加载机制来加载某个类。 JVM 和
树结构是一类重要的非线性数据结构。直观来看,树是以分支关系定义的层次结构。树结构在客观世界广泛存在,如人类社会的族谱和各种社会组织机构都可用树来形象表示。 树在计算机领域中也得到广泛应用,尤以二叉树最
@ 本文基于jdk1.8 String类可谓是我们开发中使用最多的一个类了。对于它的了解,仅仅限于API的了解是不够的,必须对它的源码进行一定的学习。 一、前置 String类是Java中非常特别的一
随便打开一个招聘网站,看看对高级Java工程师的技能要求。 抛开其它的经验能力等等,单纯从技术,或者说知识上来讲,可以发现一些共通的地方。 Java基础 计算机基础 数据库,SQL/NoSQL 常用开
@ JDBC指Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库。 1、JDBC典型用法 1.1、JDBC 4.2 常用接口和类简介
简介 ArrayList是基于数组实现的一种列表。 ArrayList继承体系如下: 图一:ArrayList继承体系 ArrayList实现了List, RandomAccess, Cloneabl
@ Java 的 IO 通过 java.io 包下的类和接口来支持, 在 java.io 包下主要包括输入、 输出两种 10 流, 每种输入、 输出流又可分为字节流和字符流两大类。 其中字节流以字节为
@ 使用断言 断言(Assertion)是一种调试程序的方式。在Java中,使用assert关键字来实现断言。 断言的概念 假设确信某个属性符合要求, 并且代码的执行依赖于这个属性。例如, 需要计算:
@ Java 程序在不同操作系统上运行时,可能需要取得平台相关的属性,或者调用平台命令来完成特定功能。 Java 提供了 System 类和 Runtime 类来与程序的运行平台进行交互。 Syste
@ Java 提供了一个操作 Set 、 List 和 Map等集合的类:Collections , 该工具类里提供了大量方法对集合元素进行排序、 查询和修改等操作,还提供了将集合对象设置为不可变、对