导读
本文适合Java入门,不太适合Java中高级软件工程师。本文以《Java核心技术基础知识卷I》第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述。本篇文章只是这个系列中的一篇,如果你喜欢这种讲解方式,或者觉得从中能学到知识,可以关注我,以便查阅本系列其他文章。
让我们开始愉快地学习Java语言吧!
![e2da58cd80cc722781df1fb8bcdb954e.png](https://i-blog.csdnimg.cn/blog_migrate/6e9c94d38b812905ef4865706d640adf.jpeg)
1断言
为啥使用断言?
断言使程序具有自我保护能力!
我们在开发和测试阶段,会加入一些检测代码辅助调试,这些代码会随其他代码一起发布,这样势必对性能有影响。断言机制允许在测试期间向代码中插入一些检査语句。当代码发布时,这些插人的检测语句将会被自动地移走。这样正式发布时,程序不会因为有大量的检查语句而影响性能。
断言只用于开发和测阶段,确定程序内部的错误位置。
断言的两种形式
1)assert 条件;
2)assert 条件:表达式;
断言执行的时候,对条件进行检测,如果条件结构为false, 则抛出一个 AssertionError异常。
第二种形式与第一种的区别就是:表达式被传入AssertionError的构造器并转换成一个消息字符串。使用这个表达式的目的只有一个:产生一个消息字符串。所以一定不要使用这个表达式向客户端传递任何跟业务相关的信息。
启用与禁用断言
那么是谁控制断言的启用与禁用呢?
这是类加载器的职责。所以启用或禁用断言时不必重新编译程序。
当断言被禁用时,类加载器将跳过断言代码。
如何启用断言呢?
在默认情况下, 断言被禁用,那么我们要像下面这样设置才能启用断言。
1)对于由类加载器加载的类而言:
用 -enableassertions 或 -ea 选项启用。
例:java -enableassertions MyApp
也可以在某个类或整个包中使用断言:
java -ea:MyClass -ea iconi.inycompany.inylib... MyApp
2)不是由类加载器加载,而是直接由虚拟机加载的类:
使用 -enablesystemassertions/-esa 开关启用断言
如何禁用断言呢?
1)对于由类加载器加载的类而言:
使用-da禁用断言
2)不是由类加载器加载,而是直接由虚拟机加载的类:
使用-dsa禁用断言
2日志
Java API提供的日志记录器
为什么要记录日志呢?
当你开发程序时,会在有问题的代码中插入System.out.println方法,以便打印执行的结果,好助你找到发生错误的位置。但是在发布时,一定要删除这些“无用”的代码,这样做太麻烦了,因此我们找到了更好的办法,那就是记录日志。至此我们有了三大武器:异常、断言、日志,使程序具有自我保护能力,同时也方便我们调试代码。
Java API提供了相应类:java.util.logging.Logger。本文简单介绍下这个类的使用,因为在日常的开发中,我们使用最多的还是其他日志组件,譬如SLF4J,log4j。
获取日志记录器
private static final Logger logger= Logger.getLogger (“LoggerName”);
LoggerName:每个日志记录器都有一个名字
为什么要将logger声明为静态变量呢?
因为未被任何变量引用的日志记录器可能会被垃圾回收,所以用一个静态变量存储日志记录器的一个引用。
日志记录器的级别
日志记录器有七个级别,从高到低依次为:SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST。
设置日志记录器的级别有什么用呢?
可以有选择地输出不同等级的记录。默认情况下,只记录前三个级别,可以使用Level.ALL开启所有级别的记录,使用Level.OFF关闭日志。
修改日志配置
一般日志配置文件位于jre/lib/1ogging.properties,可以配置java.util.logging.config.file特性,指定其他的位置。
java - Djava.util.logging.config.file=configFile MainClass。
3SLF4J
3.1 SLF4J使用模式
SLF4J是简单日志系统的Facade(门面),它为程序员提供了便利的方法,允许程序员在编写代码时不必考虑使用何种具体的日志组件,而在部署程序时在考虑这些,下面是一般的使用模式。
![a419dfb4f5703c73455cba143b06592d.png](https://i-blog.csdnimg.cn/blog_migrate/f88a795ab82b776991e86b94e33ffb6c.jpeg)
3.2 SLF4J概要
SLF4J只有一个强制依赖:slf4j-api,可以使用Maven管理依赖,例如使用1.7.25版本:
org.slf4j
slf4j-api
1.7.25
从1.6.0版本开始,如果在类路径下没有找到绑定,那么SLF4J将默认为无操作的实现。
从1.7.0版本开始,Logger接口提供了接收可变参数的打印方法,而不是如以前的接口那样参数类型为Object[]。1.6.X版本中的由编译器生成的Logger接口,1.7.X版本是无法理解的。1.7.X版本与1.6.X版本不兼容。
从1.7.5开始,显著提高了记录器检索时间。鉴于改进的程度,强烈建议用户迁移到1.7.5或更高版本。
从1.7.9版本开始,通过设置slf4j.detectLoggerNameMismatch这一系统属性为true,SLF4J能自动地发现错误命名的Logger。
3.3 SLF4J绑定
SLF4J绑定是一种jar文件,它有多种类型。
我们运行上面的例子,运行结果如下:
![45f1507c287eb4bde37a0727b646f61a.png](https://i-blog.csdnimg.cn/blog_migrate/f9fc78875bf51a95938dfc1d322eb3ca.jpeg)
打印错误的原因是,在类路径下没有找到SLF4J绑定()。
如果你将slf4j-simple的依赖配置pom.xml中上述报错就会消失。slf4j-simple是SLF4J的一个简单实现。注意引入的版本要和slf4j-api匹配,例如slf4j-api我使用1.7.25版本,那么slf4j-simple我也是使用1.7.25版本。
org.slf4j
slf4j-simple
1.7.25
运行结果为:
![c0b2afe45a577035e465f3d6fecab162.png](https://i-blog.csdnimg.cn/blog_migrate/8cafe0f9d766f7be7448589be7559a12.jpeg)
除了slf4j-simple这个绑定以外,还有几种其他类型的绑定,每种绑定都对应着一种具体日志组件。
1)slf4j-log4j12
这个绑定对应着log4j这个日志组件。pom.xml配置如下:
org.slf4j
slf4j-log4j12
1.7.21
log4j
log4j
1.2.17
2)slf4j-jdk14
这个绑定对应java.util.logging,即JDK提供的日志组件
3)slf4j-nop
这个绑定对应NOP,即no operation,默认地不记录所有日志。既然不记录日志,那么我们引入它有什么用呢?
如果不引入这个jar,那么会像上面那样输出错误信息。
4)slf4j-jcl
这个绑定对应Apache Commons Logging,也被称为 Jakarta Commons Logging。
5)logback-classic
这个绑定对应的是logback,近年来,好多公司由log4j转向logback。Logback的ch.qos.logback.classic.Logger类直接实现了org.slf4j.Logger接口,因此,将SLF4J与logback结合使用会大量地减少内存和计算的开销。
现在,想要切换日志框架是一件非常简单的事情,只要改变Maven的依赖配置就行。
切记,不能同时使用两种日志框架。
借用官网的一张图,来说明它们的关系。
![0e2a9e755430c4d3f1a8f4504f7c4d4b.png](https://i-blog.csdnimg.cn/blog_migrate/77d0d3b81f2685809d0338736bfae452.jpeg)
3.4 SLF4J+log4j示例
下面以使用log4j为例,添加log4j后。运行后发现,报错。
![8aff9f026e69df5ee4a716ed03b88167.png](https://i-blog.csdnimg.cn/blog_migrate/c2adc6ee791a9788112bbb6b96b0fb36.jpeg)
这是没有配置log4j的原因导致的。
那么我们创建资源文件夹src/main/resource,在此文件夹下添加配置文件log4j.properties,并按如下配置:
![028201e5eddc4c87dab3bc434965fc98.png](https://i-blog.csdnimg.cn/blog_migrate/42b7002b507c9a4e01ac3f90e12e4cbd.jpeg)
使用下列语句加载配置文件:
URL configURL = App.class.getClassLoader().getResource("log4j.properties");
PropertyConfigurator.configure(configURL);
运行结果如下:
![3b7ae04cd85303bb39e5328cb617dd29.png](https://i-blog.csdnimg.cn/blog_migrate/24d35107eb6aa2fa48ee76dab3f2b122.jpeg)
我们配置将info信息输出到文件,可以看到确实有一个名为info的文件。
![0581be0b936914230bc628c4c0d0f42a.png](https://i-blog.csdnimg.cn/blog_migrate/45056ad229a10dbc55fc268fbc3baf8c.jpeg)