提交 ff5cd61b 编写于 作者: 沉默王二's avatar 沉默王二 💬

异常处理 常用工具类 新特性

上级 7d3ee96d
......@@ -169,17 +169,18 @@
## 异常处理
- [一文读懂Java异常处理](docs/exception/gailan.md)
- [详解Java7新增的try-with-resouces语法](docs/exception/try-with-resouces.md)
- [一文彻底搞懂Java异常处理,YYDS](docs/exception/gailan.md)
- [深入理解 Java 中的 try-with-resouces 语法糖](docs/exception/try-with-resouces.md)
- [Java异常处理的20个最佳实践](docs/exception/shijian.md)
- [Java空指针NullPointerException的传说](docs/exception/npe.md)
## 常用工具类
- [Java Arrays工具类10大常用方法](docs/common-tool/arrays.md)
- [Java集合框架:Collections工具类](docs/common-tool/collections.md)
- [Java Arrays:专为数组而生的工具类](docs/common-tool/arrays.md)
- [Java Collections:专为集合框架而生的工具类](docs/common-tool/collections.md)
- [Hutool:国产良心工具包,让你的Java变得更甜](docs/common-tool/hutool.md)
- [Google开源的Guava工具库,太强大了~](docs/common-tool/guava.md)
- [Guava:Google开源的工具库,太强大了](docs/common-tool/guava.md)
- [这10个工具类,让我的开发效率提升了50%](docs/common-tool/utils.md)
## Java新特性
......
......@@ -165,22 +165,10 @@ export const sidebarConfig = sidebar({
collapsable: true,
prefix:"exception/",
children: [
{
text: "概览",
link: "gailan",
},
{
text: "try-with-resouces",
link: "try-with-resouces",
},
{
text: "最佳实践",
link: "shijian",
},
{
text: "NullPointerException",
link: "npe",
},
"gailan",
"try-with-resouces",
"shijian",
"npe",
],
},
{
......@@ -188,22 +176,11 @@ export const sidebarConfig = sidebar({
collapsable: true,
prefix:"common-tool/",
children: [
{
text: "Arrays",
link: "arrays",
},
{
text: "Collections",
link: "collections",
},
{
text: "Hutool",
link: "hutool",
},
{
text: "Guava",
link: "guava",
},
"arrays",
"collections",
"hutool",
"guava",
"utils",
],
},
{
......@@ -211,18 +188,9 @@ export const sidebarConfig = sidebar({
prefix: "java8/",
collapsable: true,
children: [
{
text: "Stream",
link: "stream",
},
{
text: "Optional",
link: "optional",
},
{
text: "Lambda",
link: "Lambda",
},
"stream",
"optional",
"Lambda",
],
},
{
......
---
title: Objects:专为操作 Java 对象而生的工具类
shortTitle: Objects对象工具类
category:
- Java核心
tag:
- 常用工具类
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Objects:专为操作 Java 对象而生的工具类
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,Objects
---
`jdk7`之后,提供了`Objects`工具类,我们可以通过它操作对象。
## 对象判空
在java中万事万物皆对象,对象的判空可以说无处不在。Objects的`isNull`方法判断对象是否为空,而`nonNull`方法判断对象是否不为空。例如:
```java
Integer integer = new Integer(1);
if (Objects.isNull(integer)) {
System.out.println("对象为空");
}
if (Objects.nonNull(integer)) {
System.out.println("对象不为空");
}
```
## 对象为空抛异常
如果我们想在对象为空时,抛出空指针异常,可以使用Objects的`requireNonNull`方法。例如:
```java
Integer integer1 = new Integer(128);
Objects.requireNonNull(integer1);
Objects.requireNonNull(integer1, "参数不能为空");
Objects.requireNonNull(integer1, () -> "参数不能为空");
```
## 判断两个对象是否相等
我们经常需要判断两个对象是否相等,Objects给我们提供了`equals`方法,能非常方便的实现:
```java
Integer integer1 = new Integer(1);
Integer integer2 = new Integer(1);
System.out.println(Objects.equals(integer1, integer2));
```
执行结果:
```java
true
```
但使用这个方法有坑,比如例子改成:
```java
Integer integer1 = new Integer(1);
Long integer2 = new Long(1);
System.out.println(Objects.equals(integer1, integer2));
```
执行结果:
```java
false
```
具体原因不细说了,有兴趣的小伙们可以看看我的另一篇文章《[Objects.equals有坑](https://mp.weixin.qq.com/s?__biz=MzkwNjMwMTgzMQ==&mid=2247493176&idx=1&sn=c445625478a7f8122a6715b64fe6770c&chksm=c0e83ed0f79fb7c6cf2992d24e98f60fd78ca89525b5a3cc07f79dc801dd8e381b1fce03bf5c&token=1124974571&lang=zh_CN#rd)》,里面有非常详细的讲解。
## 获取对象的hashCode
如果你想获取某个对象的hashCode,可以使用Objects的`hashCode`方法。例如:
```java
String str = new String("abc");
System.out.println(Objects.hashCode(str));
```
执行结果:
```java
96354
```
Objects的内容先介绍到这里,有兴趣的小伙们,可以看看下面更多的方法:
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/Objects-83489814-9784-4274-841a-27ee75c046ac.jpg)
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
\ No newline at end of file
---
title: Java Arrays:专为数组而生的工具类
shortTitle: Arrays工具类
category:
- Java核心
tag:
- Java
- 常用工具类
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Java Arrays工具类的10大常用方法
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,Arrays,数组
---
# Java Arrays工具类10大常用方法
“哥,数组专用工具类是专门用来操作数组的吗?比如说创建数组、数组排序、数组检索等等。”三妹的提问其实已经把答案说了出来。
......@@ -37,7 +42,7 @@ public class Arrays {}
“我们来一个一个学习。”
### 01、创建数组
## 01、创建数组
使用 Arrays 类创建数组可以通过以下三个方法:
......@@ -45,7 +50,9 @@ public class Arrays {}
- copyOfRange,复制指定范围内的数组到一个新的数组
- fill,对数组进行填充
1)copyOf,直接来看例子:
### 1)copyOf
直接来看例子:
```java
String[] intro = new String[] { "沉", "默", "王", "二" };
......@@ -73,7 +80,9 @@ private Object[] grow(int minCapacity) {
}
```
2)copyOfRange,直接来看例子:
### 2)copyOfRange
直接来看例子:
```java
String[] intro = new String[] { "沉", "默", "王", "二" };
......@@ -107,7 +116,9 @@ System.out.println(Arrays.toString(abridgementExpanded));
“嗯,我想是 Arrays 的设计者考虑到了数组越界的问题,不然每次调用 Arrays 类就要先判断很多次长度,很麻烦。”稍作思考后,我给出了这样一个回答。
3)fill,直接来看例子:
### 3)fill
直接来看例子:
```java
String[] stutter = new String[4];
......@@ -123,7 +134,7 @@ System.out.println(Arrays.toString(stutter));
如果想要一个元素完全相同的数组时, `fill()` 方法就派上用场了。
### 02、比较数组
## 02、比较数组
Arrays 类的 `equals()` 方法用来判断两个数组是否相等,来看下面这个例子:
......@@ -204,7 +215,7 @@ System.out.println(Arrays.hashCode(new String[] { "沉", "默", "王", "二" }))
两个数组的哈希值相等,毕竟元素是一样的。但这样确实不够严谨,优先使用 `Objects.equals()` 方法,当我们想快速确认两个数组是否相等时,可以通过比较 hashCode 来确认——算是投机取巧吧,高收益高风险,哈哈。
### 03、数组排序
## 03、数组排序
Arrays 类的 `sort()` 方法用来对数组进行排序,来看下面这个例子:
......@@ -227,7 +238,7 @@ System.out.println(Arrays.toString(sorted));
“不要紧的,后面学了数据结构与算法后,就明白了,现在了解这个东西即可。”我赶紧甩出了安抚大法。
### 04、数组检索
## 04、数组检索
数组排序后就可以使用 Arrays 类的 `binarySearch()` 方法进行二分查找了。否则的话,只能线性检索,效率就会低很多。
......@@ -254,7 +265,7 @@ System.out.println(caseInsensitive);
三妹若有所思的点了点头。
### 05、数组转流
## 05、数组转流
“流是什么呀?”三妹好奇的问。
......@@ -281,7 +292,7 @@ Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: origin(2) >
at java.base/java.util.Spliterators.checkFromToBounds(Spliterators.java:387)
```
### 06、打印数组
## 06、打印数组
因为数组是一个对象,直接 `System.out.println` 的话,结果是这样的:
......@@ -325,7 +336,7 @@ public static String toString(Object[] a) {
“哦----------”三妹似乎明白了什么。
### 07、数组转 List
## 07、数组转 List
尽管数组非常强大,但它自身可以操作的工具方法很少,比如说判断数组中是否包含某个值。如果能转成 List 的话,就简便多了,因为 Java 的集合框架 List 中封装了很多常用的方法。
......@@ -358,7 +369,7 @@ rets1.add("三");
rets1.remove("二");
```
### 08、setAll
## 08、setAll
Java 8 新增了 `setAll()` 方法,它提供了一个函数式编程的入口,可以对数组的元素进行填充:
......@@ -378,7 +389,7 @@ i 就相当于是数组的下标,值从 0 开始,到 9 结束,那么 `i *
可以用来为新数组填充基于原来数组的新元素。
### 09、parallelPrefix
## 09、parallelPrefix
`parallelPrefix()` 方法和 `setAll()` 方法一样,也是 Java 8 之后提供的,提供了一个函数式编程的入口,通过遍历数组中的元素,将当前下标位置上的元素与它之前下标的元素进行操作,然后将操作后的结果覆盖当前下标位置上的元素。
......@@ -415,7 +426,7 @@ System.out.println(Arrays.toString(arr));
- 第三次是 6 和 4 相加,结果是 10,也就是第二次的结果和下标为 3 的元素相加的结果
### 10、总结
## 10、总结
“好了,三妹,就先学到这吧。如果你以后翻 Java 源码的时候,只要是用到数组的,尤其是 ArrayList 类,就可以看到 Arrays 类的很多影子。”
......@@ -423,4 +434,11 @@ System.out.println(Arrays.toString(arr));
我来到客厅,坐到沙发上,捧起黄永玉先生的《无愁河上的浪荡汉子·八年卷 1》看了起来,津津有味。。。。。。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
\ No newline at end of file
---
title: Java Collections:专为集合框架而生的工具类
shortTitle: Collections工具类
category:
- Java核心
tag:
- Java
- 常用工具类
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Java Collections:专为集合框架而生的工具类
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,Collections,集合框架
---
# Java集合框架:Collections工具类
Collections 是 JDK 提供的一个工具类,位于 java.util 包下,提供了一系列的静态方法,方便我们对集合进行各种骚操作,算是集合框架的一个大管家。
......@@ -19,7 +24,7 @@ Collections 的用法很简单,在 Intellij IDEA 中敲完 `Collections.` 之
为了节省大家的学习时间,我将这些方法做了一些分类,并列举了一些简单的例子。
### 01、排序操作
## 01、排序操作
- `reverse(List list)`:反转顺序
- `shuffle(List list)`:洗牌,将顺序打乱
......@@ -66,7 +71,7 @@ System.out.println("交换后:" + list);
交换后:[沉默王三, 沉默王二, 沉默王四, 沉默王六, 沉默王五]
```
### 02、查找操作
## 02、查找操作
- `binarySearch(List list, Object key)`:二分查找法,前提是 List 已经排序过了
- `max(Collection coll)`:返回最大元素
......@@ -105,7 +110,7 @@ System.out.println("填充后的结果:" + list);
填充后的结果:[沉默王八, 沉默王八, 沉默王八, 沉默王八, 沉默王八]
```
### 03、同步控制
## 03、同步控制
[HashMap 是线程不安全](https://mp.weixin.qq.com/s/qk_neCdzM3aB6pVWVTHhNw)的,这个我们前面讲到了。那其实 ArrayList 也是线程不安全的,没法在多线程环境下使用,那 Collections 工具类中提供了多个 synchronizedXxx 方法,这些方法会返回一个同步的对象,从而解决多线程中访问集合时的安全问题。
......@@ -179,7 +184,7 @@ public class Vector<E>
正确的做法是使用并发包下的 CopyOnWriteArrayList、ConcurrentHashMap。这些我们放到并发编程时再讲。
### 04、不可变集合
## 04、不可变集合
- `emptyXxx()`:制造一个空的不可变集合
- `singletonXxx()`:制造一个只有一个元素的不可变集合
......@@ -214,7 +219,7 @@ public static final <T> List<T> emptyList() {
public static final List EMPTY_LIST = new EmptyList<>();
```
### 05、其他
## 05、其他
还有两个方法比较常用:
......@@ -250,6 +255,12 @@ addAll 后:[沉默王九, 沉默王十, 沉默王二]
这才是高手要思考的一个问题。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
......
---
title: Guava:Google开源的工具库,太强大了
shortTitle: Guava工具类
category:
- Java核心
tag:
- Java
- 常用工具类
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Guava:Google开源的工具库,太强大了
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,Guava
---
# Google开源的Guava工具库,太强大了
### 01、前世今生
## 01、前世今生
你好呀,我是 Guava。
......@@ -23,9 +29,9 @@ tag:
*PS:star 这种事,只能求,不求没效果😭😭😭。二哥开源的《Java 程序员进阶之路》专栏在 GitHub 上已经收获了 595 枚星标,铁粉们赶紧去点点啦,帮二哥冲 600 star,笔芯*
>https://github.com/itwanger/toBeBetterJavaer
>[https://github.com/itwanger/toBeBetterJavaer](https://github.com/itwanger/toBeBetterJavaer)
### 02、引入 Guava
## 02、引入 Guava
如果你要在 Maven 项目使用我的话,需要先在 pom.xml 文件中引入我的依赖。
......@@ -39,7 +45,7 @@ tag:
一点要求,JDK 版本需要在 8 以上。
### 03、基本工具
## 03、基本工具
Doug Lea,java.util.concurrent 包的作者,曾说过一句话:“null 真糟糕”。Tony Hoare,图灵奖得主、快速排序算法的作者,当然也是 null 的创建者,也曾说过类似的话:“null 的使用,让我损失了十亿美元。”鉴于此,我用 Optional 来表示可能为 null 的对象。
......@@ -70,7 +76,7 @@ possible.get(); // returns 5
- 常见的 Object 方法,比如说 Objects.equals、Objects.hashCode,JDK 7 引入的 Objects 类提供同样的方法,当然也是从我这借鉴的灵感。
- 更强大的比较器
### 04、集合
## 04、集合
首先我来说一下,为什么需要不可变集合。
......@@ -156,7 +162,7 @@ immutableList.add("马云");
### 05、字符串处理
## 05、字符串处理
字符串表示字符的不可变序列,创建后就不能更改。在我们日常的工作中,字符串的使用非常频繁,熟练的对其操作可以极大的提升我们的工作效率。
......@@ -176,7 +182,7 @@ Splitter.on(',')
.split("雷军,乔布斯,, 沉默王二");
```
### 06、缓存
## 06、缓存
缓存在很多场景下都是相当有用的。你应该知道,检索一个值的代价很高,尤其是需要不止一次获取值的时候,就应当考虑使用缓存。
......@@ -244,7 +250,88 @@ MyRemovalListener 作为缓存元素失效时的监听类,在有元素缓存
LoadingCache 就是缓存的主要操作对象了,常用的就是其中的 put 和 get 方法了。
### 07、尾声
## 07、集合工具
`com.google.common.collect`包下的集合工具:`Lists`也非常强大。
### 创建空集合
有时候,我们想创建一个空集合。这时可以用Lists的`newArrayList`方法,例如:
```java
List<Integer> list = Lists.newArrayList();
```
### 快速初始化集合
有时候,我们想给一个集合中初始化一些元素。这时可以用Lists的newArrayList方法,例如:
```java
List<Integer> list = Lists.newArrayList(1, 2, 3);
```
执行结果:
```java
[1, 2, 3]
```
### 笛卡尔积
如果你想将两个集合做`笛卡尔积`,Lists的`cartesianProduct`方法可以帮你实现:
```java
List<Integer> list1 = Lists.newArrayList(1, 2, 3);
List<Integer> list2 = Lists.newArrayList(4,5);
List<List<Integer>> productList = Lists.cartesianProduct(list1,list2);
System.out.println(productList);
```
执行结果:
```java
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
```
### 分页
如果你想将一个`大集合`分成若干个`小集合`,可以使用Lists的`partition`方法:
```java
List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
List<List<Integer>> partitionList = Lists.partition(list, 2);
System.out.println(partitionList);
```
执行结果:
```java
[[1, 2], [3, 4], [5]]
```
这个例子中,list有5条数据,我将list集合按大小为2,分成了3页,即变成3个小集合。
这个是我最喜欢的方法之一,经常在项目中使用。
比如有个需求:现在有5000个id,需要调用批量用户查询接口,查出用户数据。但如果你直接查5000个用户,单次接口响应时间可能会非常慢。如果改成分页处理,每次只查500个用户,异步调用10次接口,就不会有单次接口响应慢的问题。
### 流处理
如果我们想把某个集合转换成另外一个接口,可以使用Lists的
`transform`方法。例如:
```java
List<String> list = Lists.newArrayList("a","b","c");
List<String> transformList = Lists.transform(list, x -> x.toUpperCase());
System.out.println(transformList);
```
将小写字母转换成了大写字母。
### 颠倒顺序
Lists的有颠倒顺序的方法`reverse`。例如:
```java
List<Integer> list = Lists.newArrayList(3, 1, 2);
List<Integer> reverseList = Lists.reverse(list);
System.out.println(reverseList);
```
执行结果:
```java
[2, 1, 3]
```
list的原始顺序是312,使用`reverse`方法颠倒顺序之后,变成了213。
Lists还有其他的好用的工具,我在这里只是抛砖引玉,有兴趣的朋友,可以仔细研究一下。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/guava-4b962b06-a626-4707-9fe9-f5729536d9c5.jpg)
## 07、尾声
上面介绍了我认为最常用的功能,作为 Google 公司开源的 Java 开发核心库,个人觉得实用性还是很高的(不然呢?嘿嘿嘿)。引入到你的项目后不仅能快速的实现一些开发中常用的功能,而且还可以让代码更加的优雅简洁。
......@@ -253,4 +340,11 @@ LoadingCache 就是缓存的主要操作对象了,常用的就是其中的 put
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/guava-03.png)
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
---
title: Hutool:国产良心工具包,让你的Java变得更甜
shortTitle: Hutool工具类
category:
- Java核心
tag:
- Java
- 常用工具类
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Hutool:国产良心工具包,让你的Java变得更甜
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,Hutool
---
# Hutool:国产良心工具包,让你的Java变得更甜
读者群里有个小伙伴感慨说,“Hutool 这款开源类库太厉害了,基本上该有该的工具类,它里面都有。”讲真的,我平常工作中也经常用 Hutool,它确实可以帮助我们简化每一行代码,使 Java 拥有函数式语言般的优雅,让 Java 语言变得“甜甜的”。
Hutool 的作者在官网上说,Hutool 是 Hu+tool 的自造词(好像不用说,我们也能猜得到),“Hu”用来致敬他的“前任”公司,“tool”就是工具的意思,谐音就有意思了,“糊涂”,寓意追求“万事都作糊涂观,无所谓失,无所谓得”(一个开源类库,上升到了哲学的高度,作者厉害了)。
......@@ -19,7 +23,7 @@ Hutool 的作者在官网上说,Hutool 是 Hu+tool 的自造词(好像不用
废话就说到这,来吧,实操走起!
### 01、引入 Hutool
## 01、引入 Hutool
Maven 项目只需要在 pom.xml 文件中添加以下依赖即可。
......@@ -44,7 +48,7 @@ Hutool 对不仅对 JDK 底层的文件、流、加密解密、转码、正则
非常多,非常全面,鉴于此,我只挑选一些我喜欢的来介绍下(偷偷地告诉你,我就是想偷懒)。
### 02、类型转换
## 02、类型转换
类型转换在 Java 开发中很常见,尤其是从 HttpRequest 中获取参数的时候,前端传递的是整型,但后端只能先获取到字符串,然后再调用 `parseXXX()` 方法进行转换,还要加上判空,很繁琐。
......@@ -70,7 +74,7 @@ String unicodeStr = "沉默王二";
String unicode = Convert.strToUnicode(unicodeStr);
```
### 03、日期时间
## 03、日期时间
JDK 自带的 Date 和 Calendar 不太好用,Hutool 封装的 DateUtil 用起来就舒服多了!
......@@ -131,7 +135,7 @@ String zodiac = DateUtil.getZodiac(Month.DECEMBER.getValue(), 10);
String chineseZodiac = DateUtil.getChineseZodiac(1989);
```
### 04、IO 流相关
## 04、IO 流相关
IO 操作包括读和写,应用的场景主要包括网络操作和文件操作,原生的 Java 类库区分字符流和字节流,字节流 InputStream 和 OutputStream 就有很多很多种,使用起来让人头皮发麻。
......@@ -176,7 +180,7 @@ FileUtil.getInputStream("origin.txt")
FileUtil.getInputStream("hutool/origin.txt")
```
### 05、字符串工具
## 05、字符串工具
Hutool 封装的字符串工具类 StrUtil 和 Apache Commons Lang 包中的 StringUtils 类似,作者认为优势在于 Str 比 String 短,尽管我不觉得。不过,我倒是挺喜欢其中的一个方法的:
......@@ -186,7 +190,7 @@ String str = StrUtil.format(template, "沉默王二", "沉默王二");
// 沉默王二,一枚沉默但有趣的程序员,喜欢他的文章的话,请微信搜索沉默王二
```
### 06、反射工具
## 06、反射工具
反射机制可以让 Java 变得更加灵活,因此在某些情况下,反射可以做到事半功倍的效果。Hutool 封装的反射工具 ReflectUtil 包括:
......@@ -249,7 +253,7 @@ public class ReflectDemo {
}
```
### 07、压缩工具
## 07、压缩工具
在 Java 中,对文件、文件夹打包压缩是一件很繁琐的事情,Hutool 封装的 ZipUtil 针对 java.util.zip 包做了优化,可以使用一个方法搞定压缩和解压,并且自动处理文件和目录的问题,不再需要用户判断,大大简化的压缩解压的复杂度。
......@@ -258,7 +262,7 @@ ZipUtil.zip("hutool", "hutool.zip");
File unzip = ZipUtil.unzip("hutool.zip", "hutoolzip");
```
### 08、身份证工具
## 08、身份证工具
Hutool 封装的 IdcardUtil 可以用来对身份证进行验证,支持大陆 15 位、18 位身份证,港澳台 10 位身份证。
......@@ -270,7 +274,7 @@ boolean valid = IdcardUtil.isValidCard(ID_18);
boolean valid15 = IdcardUtil.isValidCard(ID_15);
```
### 09、扩展 HashMap
## 09、扩展 HashMap
Java 中的 HashMap 是强类型的,而 Hutool 封装的 Dict 对键的类型要求没那么严格。
......@@ -284,7 +288,7 @@ int age = dict.getInt("age");
String name = dict.getStr("name");
```
### 10、控制台打印
## 10、控制台打印
本地编码的过程中,经常需要使用 `System.out` 打印结果,但是往往一些复杂的对象不支持直接打印,比如说数组,需要调用 `Arrays.toString`。Hutool 封装的 Console 类借鉴了 JavaScript 中的 `console.log()`,使得打印变成了一个非常便捷的方式。
......@@ -304,7 +308,7 @@ public class ConsoleDemo {
}
```
### 11、字段验证器
## 11、字段验证器
做 Web 开发的时候,后端通常需要对表单提交过来的数据进行验证。Hutool 封装的 Validator 可以进行很多有效的条件验证:
......@@ -320,7 +324,7 @@ Validator.isEmail("沉默王二");
Validator.isMobile("itwanger.com");
```
### 12、双向查找 Map
## 12、双向查找 Map
Guava 中提供了一种特殊的 Map 结构,叫做 BiMap,实现了一种双向查找的功能,可以根据 key 查找 value,也可以根据 value 查找 key,Hutool 也提供这种 Map 结构。
......@@ -342,7 +346,7 @@ biMap.getKey("沉默王三");
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/hutool-06.png)
### 13、图片工具
## 13、图片工具
Hutool 封装的 ImgUtil 可以对图片进行缩放、裁剪、转为黑白、加水印等操作。
......@@ -384,7 +388,7 @@ ImgUtil.pressText(//
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/hutool-07.png)
### 14、配置文件
## 14、配置文件
>众所周知,Java 中广泛应用的配置文件 Properties 存在一个特别大的诟病:不支持中文。每次使用时,如果想存放中文字符,就必须借助 IDE 相关插件才能转为 Unicode 符号,而这种反人类的符号在命令行下根本没法看。
......@@ -423,7 +427,7 @@ public class SettingDemo {
}
```
### 15、日志工厂
## 15、日志工厂
Hutool 封装的日志工厂 LogFactory 兼容了各大日志框架,使用起来也非常简便。
......@@ -445,7 +449,7 @@ public class LogDemo {
StaticLog.info("爽啊 {}.", "沉默王二的文章");
```
### 16、缓存工具
## 16、缓存工具
CacheUtil 是 Hutool 封装的创建缓存的快捷工具类,可以创建不同的缓存对象:
......@@ -496,7 +500,7 @@ String value2 = lruCache.get("key2");
System.out.println(value2);
```
### 17、加密解密
## 17、加密解密
加密分为三种:
......@@ -544,11 +548,18 @@ public class SecureUtilDemo {
}
```
### 18、其他类库
## 18、其他类库
Hutool 中的类库还有很多,尤其是一些对第三方类库的进一步封装,比如邮件工具 MailUtil,二维码工具 QrCodeUtil,Emoji 工具 EmojiUtil,小伙伴们可以参考 Hutool 的官方文档:https://www.hutool.cn/
项目源码地址:[https://github.com/looly/hutool](https://github.com/looly/hutool)
<img src="http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png">
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
---
title: 这10个工具类,让我的开发效率提升了50%
shortTitle: 10个提升开发效率的Java工具类
category:
- Java核心
tag:
- 常用工具类
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,这10个工具类,让我的开发效率提升了50%
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,工具类,轮子
---
## IpUtil:获取本机Ip的工具类
获取本机Ip算是比较常见的一个需求场景了,比如业务报警,可能就会带上出问题的机器IP,方便直接上去看日志定位问题,那么问题来了,如何获取机器IP呢?
### 1. 基本方法
如何获取机器Ip?如果了解InetAddress这个工具类,就很容易写出一个简单的工具类,如下
```java
public static String getLocalIP() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
```
上面的实现有问题么?
当然没问题,拿我本机和阿里服务器执行一下,并没有问题如实的输出了预期的IP
本机执行后截图如下:
![本机](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/IpUtil-f35dc96f-b8ac-43d3-9393-0ff565e85fb9.jpg)
阿里云机器执行后截图如下:
![阿里云](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/IpUtil-f50b0de2-cf0d-4e9b-8f10-838ea4b47fd8.jpg)
再问一句,那是否就真的没有问题了呢?
- 在某些情况下,可能返回的是 `127.0.0.1`
在虚拟机中执行时,就可能遇到这个问题,截图如下
![虚拟机](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/IpUtil-7c14024b-57d1-4086-9f51-d7bf312b5fbf.jpg)
### 2. 进阶版
做一点简单的改动,获取IpV4的地址,源码如下
```java
/**
* 直接根据第一个网卡地址作为其内网ipv4地址,避免返回 127.0.0.1
*
* @return
*/
public static String getLocalIpByNetcard() {
try {
for (Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) {
NetworkInterface item = e.nextElement();
for (InterfaceAddress address : item.getInterfaceAddresses()) {
if (item.isLoopback() || !item.isUp()) {
continue;
}
if (address.getAddress() instanceof Inet4Address) {
Inet4Address inet4Address = (Inet4Address) address.getAddress();
return inet4Address.getHostAddress();
}
}
}
return InetAddress.getLocalHost().getHostAddress();
} catch (SocketException | UnknownHostException e) {
throw new RuntimeException(e);
}
}
```
再次测试,输出如下
![虚拟机](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/IpUtil-cd2f2acb-a6ea-4675-82a8-95a7e05c8498.jpg)
### 3. 完整工具类
```java
import java.net.*;
import java.util.Enumeration;
public class IpUtil {
public static final String DEFAULT_IP = "127.0.0.1";
/**
* 直接根据第一个网卡地址作为其内网ipv4地址,避免返回 127.0.0.1
*
* @return
*/
public static String getLocalIpByNetcard() {
try {
for (Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) {
NetworkInterface item = e.nextElement();
for (InterfaceAddress address : item.getInterfaceAddresses()) {
if (item.isLoopback() || !item.isUp()) {
continue;
}
if (address.getAddress() instanceof Inet4Address) {
Inet4Address inet4Address = (Inet4Address) address.getAddress();
return inet4Address.getHostAddress();
}
}
}
return InetAddress.getLocalHost().getHostAddress();
} catch (SocketException | UnknownHostException e) {
throw new RuntimeException(e);
}
}
public static String getLocalIP() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}
```
## CollectionUtils:Spring和Apache都有提供的集合工具类
对集合操作,除了前面说的`Collections`工具类之后,`CollectionUtils`工具类也非常常用。
目前比较主流的是`spring``org.springframework.util`包下的CollectionUtils工具类。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/CollectionUtils-3433117c-4ab2-4ac4-bf5b-4b729d87fc9a.jpg)
`apache``org.apache.commons.collections`包下的CollectionUtils工具类。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/CollectionUtils-1bc7dfe9-f459-47bb-ae4b-2a25d4be96c1.jpg)
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/CollectionUtils-2b8630a3-141b-4f18-9f54-5a37fc818420.jpg)
> 我个人更推荐使用apache的包下的CollectionUtils工具类,因为它的工具更多更全面。
举个简单的例子,`spring`的CollectionUtils工具类没有判断集合不为空的方法。而`apache`的CollectionUtils工具类却有。
下面我们以`apache`的CollectionUtils工具类为例,介绍一下常用方法。
### 集合判空
通过CollectionUtils工具类的`isEmpty`方法可以轻松判断集合是否为空,`isNotEmpty`方法判断集合不为空。
```java
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(1);
list.add(3);
if (CollectionUtils.isEmpty(list)) {
System.out.println("集合为空");
}
if (CollectionUtils.isNotEmpty(list)) {
System.out.println("集合不为空");
}
```
### 对两个集合进行操作
有时候我们需要对已有的两个集合进行操作,比如取交集或者并集等。
```java
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(1);
list.add(3);
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(4);
//获取并集
Collection<Integer> unionList = CollectionUtils.union(list, list2);
System.out.println(unionList);
//获取交集
Collection<Integer> intersectionList = CollectionUtils.intersection(list, list2);
System.out.println(intersectionList);
//获取交集的补集
Collection<Integer> disjunctionList = CollectionUtils.disjunction(list, list2);
System.out.println(disjunctionList);
//获取差集
Collection<Integer> subtractList = CollectionUtils.subtract(list, list2);
System.out.println(subtractList);
```
执行结果:
```java
[1, 2, 3, 4]
[2]
[1, 3, 4]
[1, 3]
```
说句实话,对两个集合的操作,在实际工作中用得挺多的,特别是很多批量的场景中。以前我们需要写一堆代码,但没想到有现成的轮子。
## StringUtils:专为 Java 字符串而生的工具类
`字符串`(String)在我们的日常工作中,用得非常非常非常多。
在我们的代码中经常需要对字符串判空,截取字符串、转换大小写、分隔字符串、比较字符串、去掉多余空格、拼接字符串、使用正则表达式等等。
如果只用String类提供的那些方法,我们需要手写大量的额外代码,不然容易出现各种异常。
现在有个好消息是:`org.apache.commons.lang3`包下的`StringUtils`工具类,给我们提供了非常丰富的选择。
### 字符串判空
其实空字符串,不只是null一种,还有""," ","null"等等,多种情况。
StringUtils给我们提供了多个判空的静态方法,例如:
```java
String str1 = null;
String str2 = "";
String str3 = " ";
String str4 = "abc";
System.out.println(StringUtils.isEmpty(str1));
System.out.println(StringUtils.isEmpty(str2));
System.out.println(StringUtils.isEmpty(str3));
System.out.println(StringUtils.isEmpty(str4));
System.out.println("=====");
System.out.println(StringUtils.isNotEmpty(str1));
System.out.println(StringUtils.isNotEmpty(str2));
System.out.println(StringUtils.isNotEmpty(str3));
System.out.println(StringUtils.isNotEmpty(str4));
System.out.println("=====");
System.out.println(StringUtils.isBlank(str1));
System.out.println(StringUtils.isBlank(str2));
System.out.println(StringUtils.isBlank(str3));
System.out.println(StringUtils.isBlank(str4));
System.out.println("=====");
System.out.println(StringUtils.isNotBlank(str1));
System.out.println(StringUtils.isNotBlank(str2));
System.out.println(StringUtils.isNotBlank(str3));
System.out.println(StringUtils.isNotBlank(str4));
```
执行结果:
```java
true
true
false
false
=====
false
false
true
true
=====
true
true
true
false
=====
false
false
false
true
```
示例中的:`isEmpty``isNotEmpty``isBlank``isNotBlank`,这4个判空方法你们可以根据实际情况使用。
> 优先推荐使用`isBlank`和`isNotBlank`方法,因为它会把`" "`也考虑进去。
### 分隔字符串
分隔字符串是常见需求,如果直接使用String类的split方法,就可能会出现空指针异常。
```java
String str1 = null;
System.out.println(StringUtils.split(str1,","));
System.out.println(str1.split(","));
```
执行结果:
```java
null
Exception in thread "main" java.lang.NullPointerException
\tat com.sue.jump.service.test1.UtilTest.main(UtilTest.java:21)
```
使用StringUtils的split方法会返回null,而使用String的split方法会报指针异常。
### 判断是否纯数字
给定一个字符串,判断它是否为纯数字,可以使用`isNumeric`方法。例如:
```java
String str1 = "123";
String str2 = "123q";
String str3 = "0.33";
System.out.println(StringUtils.isNumeric(str1));
System.out.println(StringUtils.isNumeric(str2));
System.out.println(StringUtils.isNumeric(str3));
```
执行结果:
```java
true
false
false
```
### 将集合拼接成字符串
有时候,我们需要将某个集合的内容,拼接成一个字符串,然后输出,这时可以使用`join`方法。例如:
```java
List<String> list = Lists.newArrayList("a", "b", "c");
List<Integer> list2 = Lists.newArrayList(1, 2, 3);
System.out.println(StringUtils.join(list, ","));
System.out.println(StringUtils.join(list2, " "));
```
执行结果:
```java
a,b,c
1 2 3
```
当然还有很多实用的方法,我在这里就不一一介绍了。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/utils-68f94af9-d2ea-46c2-81b4-7d7e08891550.jpg)
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/utils-7314260e-4e85-4110-a50d-3bedcbbeb616.jpg)
## MDC:一个线程安全的参数传递工具类
`MDC``org.slf4j`包下的一个类,它的全称是Mapped Diagnostic Context,我们可以认为它是一个线程安全的存放诊断日志的容器。
MDC的底层是用了`ThreadLocal`来保存数据的。
我们可以用它传递参数。
例如现在有这样一种场景:我们使用`RestTemplate`调用远程接口时,有时需要在`header`中传递信息,比如:traceId,source等,便于在查询日志时能够串联一次完整的请求链路,快速定位问题。
这种业务场景就能通过`ClientHttpRequestInterceptor`接口实现,具体做法如下:
第一步,定义一个LogFilter拦截所有接口请求,在MDC中设置traceId:
```java
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
MdcUtil.add(UUID.randomUUID().toString());
System.out.println("记录请求日志");
chain.doFilter(request, response);
System.out.println("记录响应日志");
}
@Override
public void destroy() {
}
}
```
第二步,实现`ClientHttpRequestInterceptor`接口,MDC中获取当前请求的traceId,然后设置到header中:
```java
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().set("traceId", MdcUtil.get());
return execution.execute(request, body);
}
}
```
第三步,定义配置类,配置上面定义的`RestTemplateInterceptor`类:
```java
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Collections.singletonList(restTemplateInterceptor()));
return restTemplate;
}
@Bean
public RestTemplateInterceptor restTemplateInterceptor() {
return new RestTemplateInterceptor();
}
}
```
其中MdcUtil其实是利用MDC工具在ThreadLocal中存储和获取traceId
```java
public class MdcUtil {
private static final String TRACE_ID = "TRACE_ID";
public static String get() {
return MDC.get(TRACE_ID);
}
public static void add(String value) {
MDC.put(TRACE_ID, value);
}
}
```
当然,这个例子中没有演示MdcUtil类的add方法具体调的地方,我们可以在filter中执行接口方法之前,生成traceId,调用MdcUtil类的add方法添加到MDC中,然后在同一个请求的其他地方就能通过MdcUtil类的get方法获取到该traceId。
能使用MDC保存traceId等参数的根本原因是,用户请求到应用服务器,Tomcat会从线程池中分配一个线程去处理该请求。
那么该请求的整个过程中,保存到MDC的ThreadLocal中的参数,也是该线程独享的,所以不会有线程安全问题。
## ClassUtils
spring的`org.springframework.util`包下的`ClassUtils`类,它里面有很多让我们惊喜的功能。
它里面包含了类和对象相关的很多非常实用的方法。
### 获取对象的所有接口
如果你想获取某个对象的所有接口,可以使用ClassUtils的`getAllInterfaces`方法。例如:
```java
Class<?>[] allInterfaces = ClassUtils.getAllInterfaces(new User());
```
### 获取某个类的包名
如果你想获取某个类的包名,可以使用ClassUtils的`getPackageName`方法。例如:
```java
String packageName = ClassUtils.getPackageName(User.class);
System.out.println(packageName);
```
### 判断某个类是否内部类
如果你想判断某个类是否内部类,可以使用ClassUtils的`isInnerClass`方法。例如:
```java
System.out.println(ClassUtils.isInnerClass(User.class));
```
### 判断对象是否代理对象
如果你想判断对象是否代理对象,可以使用ClassUtils的`isCglibProxy`方法。例如:
```java
System.out.println(ClassUtils.isCglibProxy(new User()));
```
ClassUtils还有很多有用的方法,等待着你去发掘。感兴趣的朋友,可以看看下面内容:
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/utils-c58920ac-cf04-4d95-ad29-90339a086569.jpg)
## BeanUtils
spring给我们提供了一个`JavaBean`的工具类,它在`org.springframework.beans`包下面,它的名字叫做:`BeanUtils`
让我们一起看看这个工具可以带给我们哪些惊喜。
### 拷贝对象的属性
曾几何时,你有没有这样的需求:把某个对象中的所有属性,都拷贝到另外一个对象中。这时就能使用BeanUtils的`copyProperties`方法。例如:
```java
User user1 = new User();
user1.setId(1L);
user1.setName("苏三说技术");
user1.setAddress("成都");
User user2 = new User();
BeanUtils.copyProperties(user1, user2);
System.out.println(user2);
```
### 实例化某个类
如果你想通过反射实例化一个类的对象,可以使用BeanUtils的`instantiateClass`方法。例如:
```java
User user = BeanUtils.instantiateClass(User.class);
System.out.println(user);
```
### 获取指定类的指定方法
如果你想获取某个类的指定方法,可以使用BeanUtils的`findDeclaredMethod`方法。例如:
```java
Method declaredMethod = BeanUtils.findDeclaredMethod(User.class, "getId");
System.out.println(declaredMethod.getName());
```
### 获取指定方法的参数
如果你想获取某个方法的参数,可以使用BeanUtils的`findPropertyForMethod`方法。例如:
```java
Method declaredMethod = BeanUtils.findDeclaredMethod(User.class, "getId");
PropertyDescriptor propertyForMethod = BeanUtils.findPropertyForMethod(declaredMethod);
System.out.println(propertyForMethod.getName());
```
如果你对BeanUtils比较感兴趣,可以看看下面内容:
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/utils-629ecd75-259b-46aa-b1dd-82606cfc92ee.jpg)
## ReflectionUtils
有时候,我们需要在项目中使用`反射`功能,如果使用最原始的方法来开发,代码量会非常多,而且很麻烦,它需要处理一大堆异常以及访问权限等问题。
好消息是spring给我们提供了一个`ReflectionUtils`工具,它在`org.springframework.util`包下面。
### 获取方法
如果你想获取某个类的某个方法,可以使用ReflectionUtils类的`findMethod`方法。例如:
```java
Method method = ReflectionUtils.findMethod(User.class, "getId");
```
### 获取字段
如果你想获取某个类的某个字段,可以使用ReflectionUtils类的`findField`方法。例如:
```java
Field field = ReflectionUtils.findField(User.class, "id");
```
### 执行方法
如果你想通过反射调用某个方法,传递参数,可以使用ReflectionUtils类的`invokeMethod`方法。例如:
```java
ReflectionUtils.invokeMethod(method, springContextsUtil.getBean(beanName), param);
```
### 判断字段是否常量
如果你想判断某个字段是否常量,可以使用ReflectionUtils类的`isPublicStaticFinal`方法。例如:
```java
Field field = ReflectionUtils.findField(User.class, "id");
System.out.println(ReflectionUtils.isPublicStaticFinal(field));
```
### 判断是否equals方法
如果你想判断某个方法是否equals方法,可以使用ReflectionUtils类的`isEqualsMethod`方法。例如:
```java
Method method = ReflectionUtils.findMethod(User.class, "getId");
System.out.println(ReflectionUtils.isEqualsMethod(method));
```
当然这个类还有不少有趣的方法,感兴趣的朋友,可以看看下面内容:
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/utils-0a4ecb9c-b9d2-4090-a7b7-c626a0672b94.jpg)
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
\ No newline at end of file
---
title: 一文彻底搞懂Java异常处理,YYDS
shortTitle: 一文彻底搞懂Java异常处理
category:
- Java核心
tag:
- Java
- 异常处理
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,一文彻底搞懂Java异常处理,YYDS
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,异常处理
---
# 一文读懂Java异常处理
## 一、什么是异常
“二哥,今天就要学习异常了吗?”三妹问。
......@@ -216,7 +221,7 @@ Exception in thread "main" java.lang.ArithmeticException: 年纪未满 18 岁,
at com.itwanger.s43.ThrowDemo.main(ThrowDemo.java:16)
```
“throws 关键字的作用就和 throw 完全不同。”我说,“[异常处理机制](https://mp.weixin.qq.com/s/fXRJ1xdz_jNSSVTv7ZrYGQ)这小节中讲了 checked exception 和 unchecked exception,也就是检查型异常和非检查型异常;对于检查型异常来说,如果你没有做处理,编译器就会提示你。”
“throws 关键字的作用就和 throw 完全不同。”我说,“前面的小节里已经讲了 checked exception 和 unchecked exception,也就是检查型异常和非检查型异常;对于检查型异常来说,如果你没有做处理,编译器就会提示你。”
`Class.forName()` 方法在执行的时候可能会遇到 `java.lang.ClassNotFoundException` 异常,一个检查型异常,如果没有做处理,IDEA 就会提示你,要么在方法签名上声明,要么放在 try-catch 中。
......@@ -278,7 +283,8 @@ throw new ArithmeticException("算术异常");
4)throws 关键字在声明异常的时候可以跟多个,用逗号隔开;而 throw 关键字每次只能抛出一个异常。
## 五、关于 try-catch-finally
“二哥,[上一节](https://mp.weixin.qq.com/s/fXRJ1xdz_jNSSVTv7ZrYGQ)你讲了异常处理机制,这一节讲什么呢?”三妹问。
“二哥,之前你讲了异常处理机制,这一节讲什么呢?”三妹问。
“该讲 try-catch-finally 了。”我说,“try 关键字后面会跟一个大括号 `{}`,我们把一些可能发生异常的代码放到大括号里;`try` 块后面一般会跟 `catch` 块,用来处理发生异常的情况;当然了,异常不一定会发生,为了保证发不发生异常都能执行一些代码,就会跟一个 `finally` 块。”
......@@ -460,4 +466,10 @@ static int test2 () {
至于参数 status 的值也很好理解,如果是异常退出,设置为非 0 即可,通常用 1 来表示;如果是想正常退出程序,用 0 表示即可。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
---
title: Java空指针NullPointerException的传说
shortTitle: NPE的传说
category:
- Java核心
tag:
- Java
- 异常处理
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Java空指针NullPointerException的传说
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,npe,NullPointerException
---
# Java空指针NullPointerException的传说
**空指针**,号称天下最强刺客。
......@@ -217,7 +223,13 @@ Object听到这话,皱了皱眉,他沉默了一会儿,缓缓站起身子
可是,他为什么要给我,看他刚才的样子都想打我了,又突然给了我这些?还有他一直在说的规则之力又是什么?这座城市为什么又这么诡异?
>转载链接:https://mp.weixin.qq.com/s/PDfd8HRtDZafXl47BCxyGg
>转载链接:[https://mp.weixin.qq.com/s/PDfd8HRtDZafXl47BCxyGg](https://mp.weixin.qq.com/s/PDfd8HRtDZafXl47BCxyGg)
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
---
title: Java异常处理的20个最佳实践
shortTitle: Java异常处理的20个最佳实践
category:
- Java核心
tag:
- Java
- 异常处理
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Java异常处理的20个最佳实践
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,异常处理
---
# Java异常处理的20个最佳实践
“三妹啊,今天我来给你传授几个异常处理的最佳实践经验,以免你以后在开发中采坑。”我面带着微笑对三妹说。
......@@ -15,7 +21,7 @@ tag:
--------
**1)尽量不要捕获 RuntimeException**
## 尽量不要捕获 RuntimeException
阿里出品的嵩山版 Java 开发手册上这样规定:
......@@ -43,7 +49,7 @@ try {
“的确会存在这样的情况,比如说 NumberFormatException,虽然也属于 RuntimeException,但没办法预检查,所以还是应该用 catch 捕获处理。”我说。
**2)尽量使用 try-with-resource 来关闭资源**
## 尽量使用 try-with-resource 来关闭资源
当需要关闭资源时,尽量不要使用 try-catch-finally,禁止在 try 块中直接关闭资源。
......@@ -106,7 +112,7 @@ public void closeResourceInFinally() {
}
```
**3)不要捕获 Throwable**
## 不要捕获 Throwable
Throwable 是 exception 和 error 的父类,如果在 catch 子句中捕获了 Throwable,很可能把超出程序处理能力之外的错误也捕获了。
......@@ -125,7 +131,7 @@ public void doNotCatchThrowable() {
“打个比方,一匹马只能拉一车厢的货物,拉两车厢可能就挂了,但一 catch,就发现不了问题了。”我补充道。
**4)不要省略异常信息的记录**
## 不要省略异常信息的记录
很多时候,由于疏忽大意,开发者很容易捕获了异常却没有记录异常信息,导致程序上线后真的出现了问题却没有记录可查。
......@@ -149,7 +155,7 @@ public void logAnException() {
}
```
**5)不要记录了异常又抛出了异常**
## 不要记录了异常又抛出了异常
这纯属画蛇添足,并且容易造成错误信息的混乱。
......@@ -178,7 +184,7 @@ public void wrapException(String input) throws MyBusinessException {
这种也是一样的道理,既然已经捕获了,就不要在方法签名上抛出了。
**6)不要在 finally 块中使用 return**
## 不要在 finally 块中使用 return
阿里出品的嵩山版 Java 开发手册上这样规定:
......@@ -201,9 +207,211 @@ public int checkReturn() {
“是这样的。”我点点头。
----------
## 在你的方法里抛出定义具体的检查性异常
“好了,三妹,关于异常处理实践就先讲这 6 条吧,实际开发中你还会碰到其他的一些坑,自己踩一踩可能印象更深刻一些。”我说。
```
public void foo() throws Exception { //错误方式
}
```
一定要避免出现上面的代码示例,它破坏了检查性异常的目的。 声明你的方法可能抛出的具体检查性异常,如果只有太多这样的检查性异常,你应该把它们包装在你自己的异常中,并在异常消息中添加信息。 如果可能的话,你也可以考虑代码重构。
```
public void foo() throws SpecificException1, SpecificException2 { //正确方式
}
```
## 捕获具体的子类而不是捕获 Exception 类
```
try {
someMethod();
} catch (Exception e) { //错误方式
LOGGER.error("method has failed", e);
}
```
捕获异常的问题是,如果稍后调用的方法为其方法声明添加了新的检查性异常,则开发人员的意图是应该处理具体的新异常。如果你的代码只是捕获异常(或 Throwable),永远不会知道这个变化,以及你的代码现在是错误的,并且可能会在运行时的任何时候中断。
## 在你的方法里抛出定义具体的检查性异常
```
public void foo() throws Exception { //错误方式
}
```
一定要避免出现上面的代码示例,它破坏了检查性异常的目的。 声明你的方法可能抛出的具体检查性异常,如果只有太多这样的检查性异常,你应该把它们包装在你自己的异常中,并在异常消息中添加信息。 如果可能的话,你也可以考虑代码重构。
```
public void foo() throws SpecificException1, SpecificException2 { //正确方式
}
```
## 始终正确包装自定义异常中的异常,以便堆栈跟踪不会丢失
```
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " + e.getMessage()); //错误方式
}
```
这破坏了原始异常的堆栈跟踪,并且始终是错误的,正确的做法是:
```
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " , e); //正确方式
}
```
## finally 块中永远不要抛出任何异常
```
try {
someMethod(); //Throws exceptionOne
} finally {
cleanUp(); //如果finally还抛出异常,那么exceptionOne将永远丢失
}
```
只要 cleanUp() 永远不会抛出任何异常,上面的代码没有问题,但是如果 someMethod() 抛出一个异常,并且在 finally 块中,cleanUp() 也抛出另一个异常,那么程序只会把第二个异常抛出来,原来的第一个异常(正确的原因)将永远丢失。如果在 finally 块中调用的代码可能会引发异常,请确保要么处理它,要么将其记录下来。永远不要让它从 finally 块中抛出来。
## 不要使用 printStackTrace() 语句或类似的方法
完成代码后,切勿忽略 printStackTrace(),最终别人可能会得到这些堆栈,并且对于如何处理它完全没有任何方法,因为它不会附加任何上下文信息。
## 对于不打算处理的异常,直接使用 finally
```
try {
someMethod(); //Method 2
} finally {
cleanUp(); //do cleanup here
}
```
这是一个很好的做法,如果在你的方法中你正在访问 Method 2,而 Method 2 抛出一些你不想在 Method 1 中处理的异常,但是仍然希望在发生异常时进行一些清理,然后在 finally 块中进行清理,不要使用 catch 块。
## 记住早 throw 晚 catch 原则
这可能是关于异常处理最著名的原则,简单说,应该尽快抛出(throw)异常,并尽可能晚地捕获(catch)它。应该等到有足够的信息来妥善处理它。
这个原则隐含地说,你将更有可能把它放在低级方法中,在那里你将检查单个值是否为空或不适合。而且你会让异常堆栈跟踪上升好几个级别,直到达到足够的抽象级别才能处理问题。
## 只抛出和方法相关的异常
相关性对于保持应用程序清洁非常重要。一种尝试读取文件的方法,如果抛出 NullPointerException,那么它不会给用户任何相关的信息。相反,如果这种异常被包裹在自定义异常中,则会更好。NoSuchFileFoundException 则对该方法的用户更有用。
## 切勿在程序中使用异常来进行流程控制
不要在项目中出现使用异常来处理应用程序逻辑。永远不要这样做,它会使代码很难阅读和理解。
## 尽早验证用户输入以在请求处理的早期捕获异常
始终要在非常早的阶段验证用户输入,甚至在达到 controller 之前,它将帮助你把核心应用程序逻辑中的异常处理代码量降到最低。如果用户输入出现错误,还可以保证与应用程序一致。
例如:如果在用户注册应用程序中,遵循以下逻辑:
1. 验证用户
2. 插入用户
3. 验证地址
4. 插入地址
5. 如果出问题回滚一切
这是不正确的做法,它会使数据库在各种情况下处于不一致的状态,应该首先验证所有内容,然后将用户数据置于 dao 层并进行数据库更新。正确的做法是:
1. 验证用户
2. 验证地址
3. 插入用户
4. 插入地址
5. 如果问题回滚一切
## 一个异常只能包含在一个日志中
```
LOGGER.debug("Using cache sector A");
LOGGER.debug("Using retry sector B");
```
不要像上面这样做,对多个 LOGGER.debug() 调用使用多行日志消息可能在你的测试用例中看起来不错,但是当它在具有 100 个并行运行的线程的应用程序服务器的日志文件中显示时,所有信息都输出到相同的日志文件,即使它们在实际代码中为前后行,但是在日志文件中这两个日志消息可能会间隔 100 多行。应该这样做:
```
LOGGER.debug("Using cache sector A, using retry sector B");
```
## 将所有相关信息尽可能地传递给异常
有用的异常消息和堆栈跟踪非常重要,如果你的日志不能定位异常位置,那要日志有什么用呢?
## 终止掉被中断线程
```
while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {} //别这样做
doSomethingCool();
}
```
InterruptedException 异常提示应该停止程序正在做的事情,比如事务超时或线程池被关闭等。
应该尽最大努力完成正在做的事情,并完成当前执行的线程,而不是忽略 InterruptedException。修改后的程序如下:
```
while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
break;
}
}
doSomethingCool();
```
## 对于重复的 try-catch,使用模板方法
在代码中有许多类似的 catch 块是无用的,只会增加代码的重复性,针对这样的问题可以使用模板方法。
例如,在尝试关闭数据库连接时的异常处理。
```
class DBUtil{
public static void closeConnection(Connection conn){
try{
conn.close();
} catch(Exception ex){
//Log Exception - Cannot close connection
}
}
}
```
这类的方法将在应用程序很多地方使用。不要把这块代码放的到处都是,而是定义上面的方法,然后像下面这样使用它:
```
public void dataAccessCode() {
Connection conn = null;
try{
conn = getConnection();
....
} finally{
DBUtil.closeConnection(conn);
}
}
```
## 使用 JavaDoc 中记录应用程序中的所有异常
把用 JavaDoc 记录运行时可能抛出的所有异常作为一种习惯,其中也尽量包括用户应该遵循的操作,以防这些异常发生。
---
“好了,三妹,关于异常处理实践就先讲这 20 条吧,实际开发中你还会碰到其他的一些坑,自己踩一踩可能印象更深刻一些。”我说。
“那万一到时候我工作后被领导骂了怎么办?”三妹委屈地说。
......@@ -211,6 +419,12 @@ public int checkReturn() {
“好吧。”三妹无奈地叹了口气。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
......
---
title: 深入理解 Java 中的 try-with-resouces 语法糖
shortTitle: try-with-resouces
category:
- Java核心
tag:
- Java
- 异常处理
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,深入理解 Java 中的 try-with-resouces 语法糖
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java,try-with-resouces
---
# 详解Java7新增的try-with-resouces语法
“二哥,终于等到你讲 try-with-resouces 了!”三妹夸张的表情让我有些吃惊。
“三妹,不要激动呀!开讲之前,我们还是要来回顾一下 try–catch-finally,好做个铺垫。”我说,“来看看这段代码吧。”
......@@ -296,6 +300,13 @@ java.lang.Exception: out()
“靠谱!”三妹说。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
......@@ -184,8 +184,8 @@ head:
### 异常处理
- [一文读懂Java异常处理](exception/gailan.md)
- [详解Java7新增的try-with-resouces语法](exception/try-with-resouces.md)
- [一文彻底搞懂Java异常处理,YYDS](exception/gailan.md)
- [深入理解 Java 中的 try-with-resouces 语法糖](exception/try-with-resouces.md)
- [Java异常处理的20个最佳实践](exception/shijian.md)
- [Java空指针NullPointerException的传说](exception/npe.md)
......
---
title: 深入浅出Java 8 Lambda表达式
shortTitle: Lambda表达式
category:
- Java核心
tag:
- Java
- Java新特性
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,深入浅出Java 8 Lambda表达式
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java8,lambda
---
# 深入浅出 Java 8 Lambda表达式
今天分享的主题是《Lambda 表达式入门》,这也是之前一些读者留言强烈要求我写一写的,不好意思,让你们久等了,现在来满足你们,为时不晚吧?
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/java8/Lambda-1.jpg)
### 01、初识 Lambda
## 01、初识 Lambda
Lambda 表达式描述了一个代码块(或者叫匿名方法),可以将其作为参数传递给构造方法或者普通方法以便后续执行。考虑下面这段代码:
......@@ -69,7 +74,7 @@ public class LamadaTest {
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/java8/Lambda-2.jpg)
### 02、Lambda 语法
## 02、Lambda 语法
每个 Lambda 表达式都遵循以下法则:
......@@ -176,7 +181,7 @@ c = 2;
下面我们来详细地一一介绍下。
#### 01)把 limit 变量声明为 static
### 01)把 limit 变量声明为 static
要想把 limit 变量声明为 static,就必须将 limit 变量放在 `main()` 方法外部,因为 `main()` 方法本身是 static 的。完整的代码示例如下所示。
......@@ -207,7 +212,7 @@ public class ModifyVariable2StaticInsideLambda {
OK,该方案是可行的。
#### 02)把 limit 变量声明为 AtomicInteger
### 02)把 limit 变量声明为 AtomicInteger
AtomicInteger 可以确保 int 值的修改是原子性的,可以使用 `set()` 方法设置一个新的 int 值,`get()` 方法获取当前的 int 值。
......@@ -238,7 +243,7 @@ public class ModifyVariable2AtomicInsideLambda {
OK,该方案也是可行的。
#### 03)使用数组
### 03)使用数组
使用数组的方式略带一些欺骗的性质,在声明数组的时候设置为 final,但更改 int 的值时却修改的是数组的一个元素。
......@@ -269,7 +274,7 @@ public class ModifyVariable2ArrayInsideLambda {
OK,该方案也是可行的。
### 03、Lambda 和 this 关键字
## 03、Lambda 和 this 关键字
Lambda 表达式并不会引入新的作用域,这一点和匿名内部类是不同的。也就是说,Lambda 表达式主体内使用的 this 关键字和其所在的类实例相同。
......@@ -341,10 +346,16 @@ this = com.cmower.java_demo.journal.LamadaTest@3feba861
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/java8/Lambda-4.jpg)
### 04、最后
## 04、最后
尽管 Lambda 表达式在简化 Java 编程方面做了很多令人惊讶的努力,但在某些情况下,不当的使用仍然会导致不必要的混乱,大家伙慎用。
好了,我亲爱的读者朋友们,以上就是本文的全部内容了。能在疫情期间坚持看技术文,二哥必须要伸出大拇指为你点个赞👍。原创不易,如果觉得有点用的话,请不要吝啬你手中**点赞**的权力——因为这将是我写作的最强动力。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
\ No newline at end of file
---
title: Java 8 Optional最佳指南
shortTitle: Optional最佳指南
category:
- Java核心
tag:
- Java
- Java新特性
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Java 8 Optional最佳指南
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java8,Optional
---
# Java 8 Optional最佳指南
想学习,永远都不晚,尤其是针对 Java 8 里面的好东西,Optional 就是其中之一,该类提供了一种用于表示可选值而非空引用的类级别解决方案。作为一名 Java 程序员,我真的是烦透了 NullPointerException(NPE),尽管和它熟得就像一位老朋友,知道它也是迫不得已——程序正在使用一个对象却发现这个对象的值为 null,于是 Java 虚拟机就怒发冲冠地把它抛了出来当做替罪羊。
......@@ -15,7 +20,7 @@ tag:
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/java8/optional-1.jpg)
### 01、没有 Optional 会有什么问题
## 01、没有 Optional 会有什么问题
我们来模拟一个实际的应用场景。小王第一天上班,领导老马就给他安排了一个任务,要他从数据库中根据会员 ID 拉取一个会员的姓名,然后将姓名打印到控制台。虽然是新来的,但这个任务难不倒小王,于是他花了 10 分钟写下了这段代码:
......@@ -54,7 +59,7 @@ Exception in thread "main" java.lang.NullPointerException
at com.cmower.dzone.optional.WithoutOptionalDemo.main(WithoutOptionalDemo.java:24)
```
### 02、Optional 是如何解决这个问题的
## 02、Optional 是如何解决这个问题的
小王把代码提交后,就兴高采烈地去找老马要新的任务了。本着虚心学习的态度,小王请求老马看一下自己的代码,于是老王就告诉他应该尝试一下 Optional,可以避免没有必要的 null 值检查。现在,让我们来看看小王是如何通过 Optional 来解决上述问题的。
......@@ -90,7 +95,7 @@ class Member {
Optional 之所以可以解决 NPE 的问题,是因为它明确的告诉我们,不需要对它进行判空。它就好像十字路口的路标,明确地告诉你该往哪走。
### 03、创建 Optional 对象
## 03、创建 Optional 对象
1)可以使用静态方法 `empty()` 创建一个空的 Optional 对象
......@@ -123,7 +128,7 @@ System.out.println(optOrNull); // 输出:Optional.empty
`ofNullable()` 方法内部有一个三元表达式,如果为参数为 null,则返回私有常量 EMPTY;否则使用 new 关键字创建了一个新的 Optional 对象——不会再抛出 NPE 异常了。
### 04、判断值是否存在
## 04、判断值是否存在
可以通过方法 `isPresent()` 判断一个 Optional 对象是否存在,如果存在,该方法返回 true,否则返回 false——取代了 `obj != null` 的判断。
......@@ -145,7 +150,7 @@ Optional<String> optOrNull = Optional.ofNullable(null);
System.out.println(opt.isPresent()); // 输出:true
```
### 05、非空表达式
## 05、非空表达式
Optional 类有一个非常现代化的方法——`ifPresent()`,允许我们使用函数式编程的方式执行一些代码,因此,我把它称为非空表达式。如果没有该方法的话,我们通常需要先通过 `isPresent()` 方法对 Optional 对象进行判空后再执行相应的代码:
......@@ -170,7 +175,7 @@ Optional<String> opt = Optional.of("沉默王二");
opt.ifPresentOrElse(str -> System.out.println(str.length()), () -> System.out.println("为空"));
```
### 06、设置(获取)默认值
## 06、设置(获取)默认值
有时候,我们在创建(获取) Optional 对象的时候,需要一个默认值,`orElse()``orElseGet()` 方法就派上用场了。
......@@ -249,7 +254,7 @@ orElseGet
咦,`orElseGet()` 没有去调用 `getDefaultValue()`。哪个方法的性能更佳,你明白了吧?
### 07、获取值
## 07、获取值
直观从语义上来看,`get()` 方法才是最正宗的获取 Optional 对象值的方法,但很遗憾,该方法是有缺陷的,因为假如 Optional 对象的值为 null,该方法会抛出 NoSuchElementException 异常。这完全与我们使用 Optional 类的初衷相悖。
......@@ -273,7 +278,7 @@ Exception in thread "main" java.util.NoSuchElementException: No value present
尽管抛出的异常是 NoSuchElementException 而不是 NPE,但在我们看来,显然是在“五十步笑百步”。建议 `orElseGet()` 方法获取 Optional 对象的值。
### 08、过滤值
## 08、过滤值
小王通过 Optional 类对之前的代码进行了升级,完成后又兴高采烈地跑去找老马要任务了。老马觉得这小伙子不错,头脑灵活,又干活积极,很值得培养,就又交给了小王一个新的任务:用户注册时对密码的长度进行检查。
......@@ -306,7 +311,7 @@ System.out.println(result);
这次程序输出的结果为 true,因为密码变成了 7 位,在 6 到 10 位之间。想象一下,假如小王使用 if-else 来完成这个任务,代码该有多冗长。
### 09、转换值
## 09、转换值
小王检查完了密码的长度,仍然觉得不够尽兴,觉得要对密码的强度也进行检查,比如说密码不能是“password”,这样的密码太弱了。于是他又开始研究起了 `map()` 方法,该方法可以按照一定的规则将原有 Optional 对象转换为一个新的 Optional 对象,原有的 Optional 对象不会更改。
......@@ -353,4 +358,10 @@ public class OptionalMapFilterDemo {
好了,我亲爱的读者朋友,以上就是本文的全部内容了——可以说是史上最佳 Optional 指南了,能看到这里的都是最优秀的程序员,二哥必须要伸出大拇指为你点个赞。
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
\ No newline at end of file
---
title: Java 8 Stream流详细用法
shortTitle: Stream流详细用法
category:
- Java核心
tag:
- Java
- Java新特性
description: Java程序员进阶之路,小白的零基础Java教程,从入门到进阶,Java 8 Stream流详细用法
head:
- - meta
- name: keywords
content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,java8,stream
---
# Java 8 Stream流详细用法
两个星期以前,就有读者强烈要求我写一篇 Java Stream 流的文章,我说市面上不是已经有很多了吗,结果你猜他怎么说:“就想看你写的啊!”你看你看,多么苍白的喜欢啊。那就“勉为其难”写一篇吧,嘻嘻。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/java8/stream-1.jpg)
......@@ -58,7 +60,7 @@ long count();
理论部分就扯这么多,下面直接进入实战部分。
### 01、创建流
## 01、创建流
如果是数组的话,可以使用 `Arrays.stream()` 或者 `Stream.of()` 创建流;如果是集合的话,可以直接使用 `stream()` 方法创建流,因为该方法已经添加到 Collection 接口中。
......@@ -94,11 +96,11 @@ List<Long> aList = new ArrayList<>();
Stream<Long> parallelStream = aList.parallelStream();
```
### 02、操作流
## 02、操作流
Stream 类提供了很多有用的操作流的方法,我来挑一些常用的给你介绍一下。
1)过滤
### 1)过滤
通过 `filter()` 方法可以从流中筛选出我们想要的元素。
......@@ -134,7 +136,7 @@ for (String s : strs) {
王力宏
```
2)映射
### 2)映射
如果想通过某种操作把一个流中的元素转化成新的流中的元素,可以使用 `map()` 方法。
......@@ -163,7 +165,7 @@ public class MapStreamDemo {
3
```
3)匹配
### 3)匹配
Stream 类提供了三个方法可供进行元素匹配,它们分别是:
......@@ -202,7 +204,7 @@ true
true
```
4)组合
### 4)组合
`reduce()` 方法的主要作用是把 Stream 中的元素组合起来,它有两种用法:
......@@ -248,7 +250,7 @@ public class ReduceStreamDemo {
0、1、2、3 在没有起始值相加的时候结果为 6;有起始值 6 的时候结果为 12。
### 03、转换流
## 03、转换流
既然可以把集合或者数组转成流,那么也应该有对应的方法,将流转换回去——`collect()` 方法就满足了这种需求。
......@@ -313,4 +315,10 @@ Collectors 是一个收集器的工具类,内置了一系列收集器实现,
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/java8/stream-2.jpg)
----
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)
......@@ -552,9 +552,8 @@ B 站上的这个[计算机网络微课堂](https://www.bilibili.com/video/BV1c4
我把所有的电子书都放在另外一个仓库了:
GitHub:[https://github.com/itwanger/JavaBooks](https://github.com/itwanger/JavaBooks)
码云:[https://gitee.com/itwanger/JavaBooks](https://gitee.com/itwanger/JavaBooks)
- GitHub:[https://github.com/itwanger/JavaBooks](https://github.com/itwanger/JavaBooks)
- 码云:[https://gitee.com/itwanger/JavaBooks](https://gitee.com/itwanger/JavaBooks)
## [](#常见问题解答)常见问题解答
......@@ -590,8 +589,7 @@ GitHub:[https://github.com/itwanger/JavaBooks](https://github.com/itwanger/Jav
**所涉及到的电子书,可以通过下面这个仓库下载**
GitHub:[https://github.com/itwanger/JavaBooks](https://github.com/itwanger/JavaBooks)
码云:[https://gitee.com/itwanger/JavaBooks](https://gitee.com/itwanger/JavaBooks)
- GitHub:[https://github.com/itwanger/JavaBooks](https://github.com/itwanger/JavaBooks)
- 码云:[https://gitee.com/itwanger/JavaBooks](https://gitee.com/itwanger/JavaBooks)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册