Skip to content

Files

Latest commit

8814ef5 · Oct 11, 2021

History

History
304 lines (211 loc) · 24.1 KB

File metadata and controls

304 lines (211 loc) · 24.1 KB

十二、Java 标准和外部库

甚至我们在本书中编写的第一个程序也使用了 JDK 中包含的一个库,称为标准库。如果不使用标准库,就不可能编写一个非常重要的程序。这就是为什么对这些库的熟悉与对语言本身的了解一样对成功编程至关重要的原因。

还有一些非标准库,它们被称为外部库或第三方库,因为它们不包括在 JDK 发行版中,但它们的使用频率几乎相同。他们早已成为任何程序员工具包的永久成员。同时,跟踪这些库中可用的所有功能并不像跟上 Java 本身那么容易。这是因为 IDE 为您提供了关于语言可能性的提示,但它不能建议尚未导入的包的功能。唯一一个自动导入且不需要导入的包是java.lang,这将是我们在本章中的第一个概述。

本章讨论的主题包括:

  • 什么是标准库和外部库?
  • Java 标准库概述
  • 包装java.lang
  • 包装java.util
  • 包装java.iojava.nio
  • 包装java.sqljavax.sql
  • 包装java.net
  • 包装java.math
  • 包装java.awtjavax.swingjavafx
  • Java 外部库概述
  • 图书馆org.junit
  • 图书馆org.mockito
  • 图书馆org.log4jorg.slf4j
  • 图书馆org.apache.commons
  • 练习-使用java.time.LocalDateTime

什么是标准库和外部库?

标准库(也称为类标准库)是可用于该语言所有实现的类和接口的集合。更简单地说,这意味着,它是 JDK 中包含的准备使用的.class文件的集合。一旦您安装了 Java,您就可以将它们作为安装的一部分,并可以开始使用标准库的类作为构建块来构建应用程序代码,这些构建块负责许多底层管道。标准库的丰富性和易用性极大地促进了 Java 的普及。

这些集合是按包组织的。这就是为什么程序员称之为 Java 标准库(Java standard library)而不是称之为 Java 标准库(Java standard library),因为为了使用它们,您必须根据需要导入库包,因此它们被视为许多库。

它们也是标准的,因为 Maven 会自动将它们添加到类路径中,所以我们不需要将它们作为依赖项列在pom.xml文件中。这就是标准库和外部库的区别;如果您需要在 Maven 配置文件pom.xml中添加一个库(通常为.jar文件)作为依赖项,则该库是一个外部库,也称为第三方库。否则,它是一个标准库。

在以下各节中,我们将对每个类别进行概述,并进一步了解一些最流行的标准库和外部库。

Java 标准库

如果您在 internet 上搜索“JavaAPI”,您将发现 JDK 中包含的所有包的在线描述。一些包名称以java开头。它们传统上被称为核心 Java 包,而那些以javax开头的被称为扩展。这样做可能是因为扩展被认为是可选的,甚至可能独立于 JDK 发布。也有人试图将以前的扩展库提升为核心包,但这需要将包的名称从 Java 更改为 Javax,这将破坏现有的应用程序。因此,这个想法被抛弃了,扩展成为 JDK 的标准部分,成为核心,核心和扩展之间的区别逐渐消失。

这就是为什么如果您查看 Oracle 网站上的官方 Java API,您将看到不仅有javajavax包被列为标准,还有jdkcom.sunorg.xml和其他一些包也被列为标准。这些额外的包主要由工具或其他专用应用程序使用。在本书中,我们将主要关注主流 Java 编程,只讨论javajavax包。

java.lang

这个包对于所有 Java 类库来说都是非常基本的,因此它不仅不需要作为依赖项列在 Maven 配置pom.xml文件中(Java 标准库的所有其他包也不需要作为依赖项列出来),而且它的成员甚至不需要为了使用它们而导入。任何包的任何成员,无论是否为标准,都必须导入或使用其完全限定名,但java.lang包的类和接口除外。原因是它包含两个最重要和最常用的 Java 类:

  • Object:任何其他 Java 类的基类(参见第 2 章Java 语言基础
  • Class:其实例在运行时携带每个加载类的元数据(参见第 11 章JVM 进程和垃圾收集

此外,java.lang包还包括:

  • 支持类型为String的操作的类StringStringBufferStringBuilders(更多详细信息和用法示例,请参见第 15 章管理对象、字符串、时间和随机数
  • 所有原语类型的包装类:ByteBooleanShortCharacterIntegerLongFloatDouble(有关包装类及其用法的详细信息,请参见第 9 章运算符、表达式和语句
  • Number类,前面列出的数字包装类的基类
  • System类,提供对重要系统操作和标准输入输出的访问(我们在本书的每个代码示例中都使用了System.out对象)
  • Runtime类,提供对执行环境的访问
  • Thread类和Runnable接口是创建 Java 线程的基础
  • 迭代语句使用的Iterable接口(参见第 9 章运算符、表达式、语句 ** Math类,提供基本数值操作的方法* Throwable类–所有异常的基类* 异常类Error及其所有子类,用于传递应用程序不应捕获的系统错误* Exception类及其多个子类,表示已检查的异常(参见第 10 章控制流语句)* RuntimeException类及其多个子类表示未检查的异常,也称为运行时异常(参见第 10 章控制流语句)* ClassLoader类,它允许加载类,并可用于构建定制的类加载器* ProcessProcessBuilder类,它们允许创建外部进程* 许多其他有用的类和接口*

*# java.util

这是另一个非常常用的包。其大部分内容专用于支持收藏:

  • Collection接口–许多采集接口的基础接口。它包含管理集合元素所需的所有基本方法:size()add()remove()contains()iterator()stream()等。请注意,Collection接口扩展了Iterable接口并从中继承了iterator()方法。这意味着Collection接口的任何实现都可以在迭代语句中使用。
  • 扩展Collection接口的接口:ListSetQueueDeque等。
  • 许多实现上述接口的类:ArrayListLinkedListHashSetAbstractQueueArrayDeque等。
  • Map接口和实现它的类:HashMapTreeMap等。
  • Collections类,它提供了许多用于操作和转换集合的静态方法。
  • 许多其他集合接口、类和相关实用程序。

我们将更多地讨论集合,并在第 13 章Java 集合中看到它们的用法示例。

java.util包还包括其他几个有用的类:

  • Objects类提供了各种与对象相关的实用方法,包括两个对象的空安全equals()
  • Arrays类包含 200 多个静态方法来操作数组
  • Formatter类允许格式化任何基元类型,如StringDate和其他类型
  • OptionalOptionalIntOptionalLongOptionalDouble,它们通过包装实际值来帮助避免NullPointerException,不管实际值是否为空
  • Properties类帮助读取和创建用于配置和类似目的的键值对
  • Random类通过生成伪随机数流来补充Math.random()方法
  • Stack类允许创建对象的后进先出后进先出堆栈
  • StringTokeneizer类将String对象分解为由指定分隔符分隔的标记
  • StringJoiner类构造由指定分隔符分隔的字符序列,并可选地由指定的前缀和后缀包围
  • 许多其他有用的实用程序类,包括国际化支持类和 base64 编码和解码

java.time

这是管理日期、时间、实例和持续时间的主要 JavaAPI。一揽子计划包括:

  • 枚举Month
  • 枚举DayOfWeek
  • Clock类,它使用时区立即返回当前日期和时间
  • DurationPeriod类表示并比较不同时间单位中的时间量
  • LocalDateLocalTimeLocalDateTime类表示没有时区的日期和时间
  • ZonedDateTime类表示带时区的日期时间
  • ZoneId类标识一个时区,如美国/芝加哥
  • 其他一些支持日期和时间操作的类

java.time.format.DateTimeFormatter类允许您按照国际标准组织ISO)格式显示日期和时间,并基于 YYYY-MM-DD 等模式。

我们将进一步讨论日期和时间处理,参见第 15 章管理对象、字符串、时间和随机数中的代码示例。

java.io 和 java.nio

java.iojava.nio包包含支持使用流、序列化和文件系统读写数据的类。这两个包的区别如下:

  • java.io允许我们在不缓存的情况下读取/写入数据
  • java.nio创建一个缓冲区,允许程序在缓冲区中来回移动
  • java.io的类方法阻塞流,直到读取或写入所有数据
  • java.nio表示数据读写的非阻塞方式

java.sql 和 javax.sql

这两个包组成了Java 数据库连接JDBC)API,它允许访问和处理存储在数据源(通常是关系数据库)中的数据。包javax.sql补充了java.sql包,为以下方面提供支持:

  • DataSource接口作为DriverManager的替代
  • 连接池和语句池
  • 分布式事务
  • 行集

我们将进一步讨论如何使用这些包,并在第 16 章数据库编程中查看代码示例。

java.net

java.net包包含支持两个级别的应用程序联网的类:

  • 低层网络,基于:

    • IP 地址
    • 套接字,是基本的双向数据通信机制
    • 各种网络接口
  • 高级网络,基于:

    • 通用资源标识符URI
    • 通用资源定位器URL
    • 到 URL 指向的资源的连接

java.math

该包通过允许使用类BigDecimalBigInteger处理更大的数字,补充了java.lang包的 Java 基本类型和包装类。

awt、javax.swing 和 javafx

第一个支持为桌面应用程序构建图形用户界面GUI)的 Java 库是java.awt包中的抽象窗口工具包AWT)。它为执行平台的本机系统提供了一个接口,允许创建和管理窗口、布局和事件。它还提供了从浏览器到浏览器的基本菜单和窗口小部件。它对本机代码的高度依赖使得基于 AWT 的 GUI 在不同平台上看起来有所不同。

1997,Sun MetaSnices 和 Netscape 通信公司引入 java 基础类,后来称为 Swing,并放入包 Tyt0.使用 Swing 构建的 GUI 组件可以模拟一些本机平台的外观,但也允许用户插入不依赖于其运行平台的外观。它通过添加选项卡式面板、滚动窗格、表格和列表扩展了 GUI 可能拥有的小部件列表。Swing 组件被称为轻量级组件,因为它们不依赖于本机代码,并且完全用 Java 实现。

2007 年,Sun Microsystems 发布了 JavaFX,它最终成为一个软件平台,用于在许多不同的设备上创建和交付桌面应用程序,以取代 Swing 作为 JavaSE 的标准 GUI 库。它位于以javafx开头的包中,支持所有主要的桌面操作系统和多个移动操作系统,包括 Symbian 操作系统、Windows mobile 和一些专有的实时操作系统。

JavaFX 为 GUI 开发人员增加了对平滑动画、web 视图、音频和视频播放以及基于级联样式表CSS的样式的支持。然而,Swing 有更多的组件和第三方库,因此使用 JavaFX 可能需要创建在 Swing 中很久以前就已经实现的自定义组件和管道。这就是为什么根据 Oracle 网站(上的官方回复,尽管 JavaFX 被推荐为桌面 GUI 实现的首选,但 Swing 在可预见的未来仍将是 Java 的一部分 http://www.oracle.com/technetwork/java/javafx/overview/faq-1446554.html#6 )。因此,可以继续使用 Swing,但如果可能,最好切换到 JavaFX。

Java 外部库

各种统计数据包括 20 个或 100 个最常用的第三方库列表中的不同名称。在本节中,我们将讨论这些列表中的大部分。所有这些都是开源项目。

org.junit

JUnit 是一个开源测试框架,其根包名为org.junit。在本书的几个代码示例中都使用了它。如您所见,它的设置和使用非常简单(我们已经在第 4 章您的第一个 Java 项目中描述了步骤):

  • 向 Maven 配置文件pom.xml添加依赖项
  • 手动创建测试,或右键单击要测试的类名,选择“转到”,然后选择“测试”,然后选择“创建新测试”,然后检查要测试的类的方法
  • 使用注释@Test为生成的测试方法编写代码
  • 如有必要,添加带有注释@Before@After的方法

“单元”是可以测试的最小代码段,因此是名称。最好的测试实践认为方法是最小的可测试单元。这就是为什么单元测试通常是测试方法。

org.mockito

单元测试经常面临的问题之一是需要测试使用第三方库、数据源或其他类的方法的方法。在测试时,您希望控制所有输入,以便能够准确预测测试代码的预期结果。这就是模拟或模拟被测试代码与之交互的对象行为的技术的用武之地。

开源框架 Mockito(根包名称org.mockito)允许您准确地完成这一点——创建模拟对象。它使用起来非常简单和直接。这里有一个简单的例子:

  • 向 Maven 配置文件pom.xml添加依赖项
  • 为需要模拟的类调用mock()方法:SomelClass mo = Mockito.mock(SomeClass.class)
  • 设置需要从方法返回的值:Mockito.when(mo.doSomething(10)).thenReturn(20)
  • 现在,将模拟对象作为参数传递给正在测试的调用模拟方法的方法
  • mock 方法返回预定义的结果

Mockito 有一定的局限性。例如,不能模拟静态方法和私有方法。否则,通过可靠地预测所用方法的结果来隔离您正在测试的代码是一种很好的方法。该框架的名称和徽标基于mojitos——一种饮料。

org.apache.log4j 和 org.slf4j

在本书中,我们使用了System.out对象来显示中间和最终结果的输出。在实际应用程序中,您也可以这样做,并将输出重定向到文件,例如,用于以后的分析。在做了一段时间后,您会注意到需要关于每个输出的更多详细信息—例如,每个语句的日期和时间,或者生成该语句的类名。随着代码库的增长,您会发现最好将不同子系统或包的输出发送到不同的文件,或者在一切正常时关闭一些消息,在检测到问题并且需要有关代码行为的更详细信息时重新打开这些消息。

您可以编写自己的程序来完成所有这些,但是有几个框架可以根据配置文件中的设置来完成,您可以在每次需要更改消息行为时更改这些设置。应用程序日志中使用的【JAY-log】和【T4-T0】等四条消息,最常用的是【应用程序日志】中的【JAY-log】和【T4-T0】这四条消息。

事实上,这两个框架并不是竞争对手。slf4j是一个门面,提供对底层日志框架的统一访问,其中一个也可以是log4j。当程序员事先不知道使用库的应用程序将使用什么样的日志框架时,这种外观在库开发期间尤其有用。通过使用slf4j编写代码,程序员允许用户稍后将其配置为使用任何日志系统。

因此,如果您的代码将仅由您的团队开发的应用程序使用,并且将在生产中支持,那么只使用log4j就足够了。否则,考虑使用 OutT1。

而且,与任何第三方库一样,在使用任何日志框架之前,必须向 Maven 配置文件pom.xml添加相应的依赖项。

org.apache.commons

在上一节中,我们讨论了一个具有org.apache根名称的包—包org.apache.log4j

包 AutoT0.是另一个流行的库,代表一个名为 Apache Care 的项目,它被称为 Apache 软件基金会的开源程序员社区维护。该组织于 1999 年由 Apache 集团成立。自 1993 年以来,Apache 集团一直围绕着 Apache HTTP 服务器的开发而发展。ApacheHTTP 服务器是一种开源的跨平台 web 服务器,自 1996 年 4 月以来一直是最流行的。来自维基百科的一篇文章:

“截至 2016 年 7 月,据估计,它服务于 46%的所有活跃网站和 43%的百万顶级网站。“Apache”这个名字是从对土著美洲阿帕奇民族的尊重中选择的,因为他们在战争战略方面的高超技能和他们无尽的耐力而闻名。这也让人联想到了“一个零碎的 web 服务器”“-由一系列修补程序组成的服务器,但这不是其来源”

Apache Commons 项目包括三个部分:

  • Commons 沙盒:用于 Java 组件开发的工作空间;您可以在那里为开源工作做出贡献
  • Commons 休眠:当前处于非活动状态的组件的存储库;您可以在那里使用代码,但必须自己构建组件,因为这些组件可能不会在不久的将来发布
  • Commons 本体:可重用 Java 组件,组成实际库org.apache.commons

在以下小节中,我们将只讨论 Commons Prime 最流行的四个包:

  • org.apache.commons.io
  • org.apache.commons.lang
  • org.apache.commons.lang3
  • org.apache.commons.codec.binary

然而,在org.apache.commons下还有更多的包,其中包含数千个有用的类,这些类可以很容易地使用,并有助于使您的代码优雅高效。

org.apache.commons.io

org.apache.commons.io包的所有类都包含在根包和五个子包中:

  • 根包org.apache.commons.io包含具有执行常见任务的静态方法的实用程序类,例如,一个流行的FileUtils类,它允许对所需文件执行所有可能的操作:

    • 写入文件
    • 从文件中读取
    • 创建一个目录,包括父目录
    • 复制文件和目录
    • 删除文件和目录
    • 与 URL 之间的转换
    • 按筛选器和扩展名列出文件和目录
    • 比较文件内容
    • 文件上次更改日期
    • 计算校验和
  • org.apache.commons.io.input包包含支持基于InputStreamReader实现的数据输入的类,如XmlStreamReaderReversedLinesFileReader

  • org.apache.commons.io.output包包含支持基于OutputStreamWriter实现的数据输出的类,如XmlStreamWriterStringBuilderWriter

  • org.apache.commons.io.filefilter包包含用作文件过滤器的类,如DirectoryFileFilterRegexFileFilter

  • org.apache.commons.io.comparato包包含各种文件的java.util.Comparator实现,如NameFileComparator

  • org.apache.commons.io.monitor包提供用于监控文件系统事件(目录和文件创建、更新和删除事件)的组件,例如FileAlterationMonitor,它实现Runnable并生成一个监控线程,以指定的间隔触发任何已注册的FileAlterationObserver

org.apache.commons.lang 和 lang3

org.apache.commons.lang3实际上是包org.apache.commons.lang的版本 3。创建新包的决定是由于版本 3 中引入的更改是向后不兼容的。这意味着使用先前版本的org.apache.commons.lang包的现有应用程序在升级到版本 3 后可能会停止工作。但是,在大多数主流编程中,在 import 语句中添加 3(作为迁移到新版本的方式)可能不会破坏任何东西。

根据文档“org.apache.commons.lang3 包提供了高度可重用的静态实用程序方法,主要涉及为 java.lang 类增加价值。以下是几个值得注意的示例:

  • ArrayUtils类允许搜索和操作数组。
  • ClassUtils类提供了一些关于类的元数据。
  • ObjectUtils类检查对象数组中的null,比较对象,并以空安全的方式计算对象数组的中值和最小/最大值。
  • SystemUtils类提供有关执行环境的信息。
  • ThreadUtils类查找有关当前正在运行的线程的信息。
  • Validate类验证单个值和集合:比较它们,检查null,匹配,并执行许多其他验证。
  • RandomStringUtils类从各种字符集的字符生成String对象。
  • StringUtils类是许多程序员的最爱。以下是它提供的空安全操作列表:
    • isEmpty/isBlank:检查String值是否包含文本
    • trim/strip:删除前导和尾随空格
    • equals/compare:比较两个空安全字符串
    • startsWith:检查String值是否以某个前缀 null safe 开头
    • endsWith:检查String值是否以某个后缀 null safe 结尾
    • indexOf/lastIndexOf/contains:提供检查的空安全索引
    • indexOfAny/lastIndexOfAny/indexOfAnyBut/lastIndexOfAnyBut:提供一组String值中任意一个的索引
    • containsOnly/containsNone/containsAny:检查String值是否仅包含/无/任何特定字符
    • substring/left/right/mid:支持空安全子串提取
    • substringBefore/substringAfter/substringBetween:相对于其他字符串执行子字符串提取
    • split/join:通过特定分隔符将String值拆分为子字符串数组,反之亦然
    • remove/delete:删除String值的一部分
    • replace/overlay:搜索一个String值并用另一个值替换一个String
    • chomp/chop:删除String值的最后一部分
    • appendIfMissing:如果String值不存在,则在其末尾添加后缀
    • prependIfMissing:如果String值不存在,则在其开头加前缀
    • leftPad/rightPad/center/repeat:此焊盘为String
    • upperCase/lowerCase/swapCase/capitalize/uncapitalize:这改变了String值的情况
    • countMatches:统计一个String值在另一个String值中出现的次数
    • isAlpha/isNumeric/isWhitespace/isAsciiPrintable:检查String值中的字符
    • defaultString:这可以防止String值的null输入
    • rotate:以String值旋转(循环移位)字符
    • reverse/reverseDelimited:这将反转String值中的字符或分隔字符组
    • abbreviate:使用省略号或其他给定String值缩写String
    • difference:比较String值并报告其差异
    • levenshteinDistance:将一个String值更改为另一个String值所需的更改次数

org.apache.commons.codec.binary

此库的内容不在本入门课程的范围内。所以,我们将只提到这个库提供了对 Base64、Base32、二进制和十六进制字符串编码和解码的支持。

由于不同协议中字符范围的限制,编码是确保跨不同系统发送的数据不会在途中更改的必要条件。此外,一些系统将发送的数据解释为控制字符(例如调制解调器)。

练习–比较 String.indexOf()和 StringUtils.indexOf()

String类的indexOf()方法和StringUtils类的indexOf()方法有什么区别?

答复

String类的indexOf()方法不处理null。下面是一些演示代码:

String s = null;
int i = StringUtils.indexOf(s, "abc");     //return -1
s.indexOf("abc");                          //throws NullPointerException

总结

在本章中,读者了解了 JDK 中包含的 Java 标准库以及一些最流行的外部库或第三方库的内容。特别是,我们仔细研究了标准包java.langjava.util;比较包装java.iojava.niojava.sqljavax.sqljava.awtjavax.swingjavafx;并对包装java.netjava.math进行了审查。

我们还对流行的外部库org.junitorg.mockitoorg.apache.log4jorg.slf4j以及 Apache Commons 项目的几个包org.apache.commons.ioorg.apache.commons.langorg.apache.commons.lang3org.apache.commons.codec.binary进行了概述。

下一章将帮助读者更详细地熟悉最广泛使用的 Java 类。代码示例将说明对名为集合的类的功能的讨论:ListArrayListSetHashSet以及MapHashMap。我们还将讨论课程ArraysArrayUtilsObjectsObjectUtilsStringBuilderStringBufferLocalDateLocalTimeLocalDateTime。*