Objects.md 8.0 KB
Newer Older
1
---
沉默王二's avatar
沉默王二 已提交
2
title: Objects:专为操作Java对象而生的工具类
沉默王二's avatar
沉默王二 已提交
3
shortTitle: Objects工具类
4 5 6 7
category:
  - Java核心
tag:
  - 常用工具类
沉默王二's avatar
沉默王二 已提交
8
description: 本文详细介绍了Java中的Objects工具类,阐述了它在处理Java对象操作中的实际应用和优势。通过具体的代码示例,展示了如何使用Objects类解决对象比较、判空、生成hashCode等常见问题。学习Objects工具类的技巧,让您在Java编程中更加高效地处理对象操作,提高开发效率。
9 10 11
head:
  - - meta
    - name: keywords
沉默王二's avatar
沉默王二 已提交
12
      content: Java,Java SE,Java基础,Java教程,二哥的Java进阶之路,Java进阶之路,Java入门,教程,java,Objects,java objects
13 14
---

沉默王二's avatar
沉默王二 已提交
15
# 9.4 Objects工具类
沉默王二's avatar
沉默王二 已提交
16

沉默王二's avatar
沉默王二 已提交
17
Java 的 Objects 类是一个实用工具类,包含了一系列静态方法,用于处理对象。它位于 java.util 包中,自 Java 7 引入。Objects 类的主要目的是降低代码中的[空指针异常](https://javabetter.cn/exception/npe.html) (NullPointerException) 风险,同时提供一些非常实用的方法供我们使用。
沉默王二's avatar
沉默王二 已提交
18 19 20 21

### 对象判空

在 Java 中,万物皆对象,对象的判空可以说无处不在。Objects 的 `isNull` 方法用于判断对象是否为空,而 `nonNull` 方法判断对象是否不为空。例如:
22 23 24 25 26 27 28 29 30 31 32 33 34

```java
Integer integer = new Integer(1);

if (Objects.isNull(integer)) {
    System.out.println("对象为空");
}

if (Objects.nonNull(integer)) {
    System.out.println("对象不为空");
}
```

沉默王二's avatar
沉默王二 已提交
35 36
### 对象为空时抛异常

沉默王二's avatar
沉默王二 已提交
37
如果我们想在对象为空时,抛出[空指针异常](https://javabetter.cn/exception/npe.html),可以使用 Objects 的 `requireNonNull` 方法。例如:
沉默王二's avatar
沉默王二 已提交
38

39 40 41 42 43 44 45 46
```java
Integer integer1 = new Integer(128);

Objects.requireNonNull(integer1);
Objects.requireNonNull(integer1, "参数不能为空");
Objects.requireNonNull(integer1, () -> "参数不能为空");
```

沉默王二's avatar
沉默王二 已提交
47 48 49 50
### 判断两个对象是否相等

我们经常需要判断两个对象是否相等,Objects 给我们提供了 `equals` 方法,能非常方便的实现:

51 52 53 54 55 56
```java
Integer integer1 = new Integer(1);
Integer integer2 = new Integer(1);

System.out.println(Objects.equals(integer1, integer2));
```
沉默王二's avatar
沉默王二 已提交
57

58
执行结果:
沉默王二's avatar
沉默王二 已提交
59

60 61 62
```java
true
```
沉默王二's avatar
沉默王二 已提交
63

64
但使用这个方法有坑,比如例子改成:
沉默王二's avatar
沉默王二 已提交
65

66 67 68 69 70 71
```java
Integer integer1 = new Integer(1);
Long integer2 = new Long(1);

System.out.println(Objects.equals(integer1, integer2));
```
沉默王二's avatar
沉默王二 已提交
72

73
执行结果:
沉默王二's avatar
沉默王二 已提交
74

75 76 77 78
```java
false
```

沉默王二's avatar
沉默王二 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
不过,需要注意的是,虽然 `Objects.equals()` 方法本身是用来避免坑的,因为它可以处理 null 值的比较,而不会抛出空指针异常。然而,这并不意味着它没有任何潜在问题。实际上,`Objects.equals()` 方法的一个潜在问题是依赖于被比较对象的 `equals()` 方法实现。

当两个对象的类没有正确实现 `equals()` 方法时,`Objects.equals()` 方法可能会产生不符合预期的结果。举个例子:

```java
public class ObjectsDemo1 {
    public static void main(String[] args) {
        Person person1 = new Person("沉默王二", 18);
        Person person2 = new Person("沉默王二", 18);

        System.out.println(Objects.equals(person1, person2)); // 输出:false
    }
}
class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
```

在上面的例子中,我们创建了一个名为 Person 的类,但是没有重写 `equals()` 方法。然后我们创建了两个具有相同属性的 Person 对象,并使用 `Objects.equals()` 方法比较它们。尽管这两个对象的属性是相同的,但输出结果却是 false。这是因为 `Objects.equals()` 方法依赖于对象的 `equals()` 方法,而在这个例子中,Person 类没有正确地实现 `equals()` 方法,所以默认情况下会使用 Object 类的 `equals()` 方法,它只比较对象引用是否相同。

为了解决这个问题,我们需要在 Person 类中重写 `equals()` 方法:

107
```java
沉默王二's avatar
沉默王二 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
        return false;
    }
    Person person = (Person) obj;
    return age == person.age && Objects.equals(name, person.name);
}
```

现在,当我们使用 `Objects.equals()` 方法比较两个具有相同属性的 Person 对象时,输出将是 true,符合我们的预期。

### 获取对象的hashCode

如果你想获取某个对象的 hashCode,可以使用 Objects 的 `hashCode` 方法。例如:

```java
String str = new String("沉默王二");
129 130
System.out.println(Objects.hashCode(str));
```
沉默王二's avatar
沉默王二 已提交
131

132
执行结果:
沉默王二's avatar
沉默王二 已提交
133

134
```java
沉默王二's avatar
沉默王二 已提交
135
867758096
136 137
```

沉默王二's avatar
沉默王二 已提交
138 139
### 比较两个对象

沉默王二's avatar
沉默王二 已提交
140
`compare()` 方法用于比较两个对象,通常用于自定义排序。它需要一个[比较器 (Comparator) ](https://javabetter.cn/basic-extra-meal/comparable-omparator.html)作为参数。如果比较器为 null,则使用自然顺序。以下是一个 `compare()` 方法的示例:
沉默王二's avatar
沉默王二 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

```java
class ObjectsCompareDemo {
    public static void main(String[] args) {
        PersonCompare person1 = new PersonCompare("itwanger", 30);
        PersonCompare person2 = new PersonCompare("chenqingyang", 25);

        Comparator<PersonCompare> ageComparator = Comparator.comparingInt(p -> p.age);
        int ageComparisonResult = Objects.compare(person1, person2, ageComparator);
        System.out.println("年龄排序: " + ageComparisonResult); // 输出:1(表示 person1 的 age 在 person2 之后)
    }
}

class PersonCompare {
    String name;
    int age;

    PersonCompare(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
```

### 比较两个数组

沉默王二's avatar
沉默王二 已提交
167
`deepEquals()` 用于比较两个[数组类型](https://javabetter.cn/array/array.html)的对象,当对象是非数组的话,行为和 `equals()` 一致。
沉默王二's avatar
沉默王二 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

```java
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
int[] array3 = {1, 2, 4};

System.out.println(Objects.deepEquals(array1, array2)); // 输出:true(因为 array1 和 array2 的内容相同)
System.out.println(Objects.deepEquals(array1, array3)); // 输出:false(因为 array1 和 array3 的内容不同)

// 对于非数组对象,deepEquals() 的行为与 equals() 相同
String string1 = "hello";
String string2 = "hello";
String string3 = "world";

System.out.println(Objects.deepEquals(string1, string2)); // 输出:true(因为 string1 和 string2 相同)
System.out.println(Objects.deepEquals(string1, string3)); // 输出:false(因为 string1 和 string3 不同)
```

沉默王二's avatar
沉默王二 已提交
186
再来个[二维数组](https://javabetter.cn/array/double-array.html)的:
沉默王二's avatar
沉默王二 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200

```java
String[][] nestedArray1 = {{"A", "B"}, {"C", "D"}};
String[][] nestedArray2 = {{"A", "B"}, {"C", "D"}};
String[][] nestedArray3 = {{"A", "B"}, {"C", "E"}};

System.out.println(Objects.deepEquals(nestedArray1, nestedArray2)); // 输出:true (因为嵌套数组元素相同)
System.out.println(Objects.deepEquals(nestedArray1, nestedArray3)); // 输出:false (因为嵌套数组元素不同)
```

### 小结

除了上面提到的这些方法,Objects 还提供了一些其他的方法,比如说 toString,感兴趣的话可以试一下。

沉默王二's avatar
沉默王二 已提交
201
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/common-tool/Objects-83489814-9784-4274-841a-27ee75c046ac.jpg)
202

沉默王二's avatar
沉默王二 已提交
203 204
总之,Objects 类提供的这些方法在许多情况下还是非常有用得,可以简化代码并减少出错的可能性。

205 206
----

沉默王二's avatar
9000+  
沉默王二 已提交
207
GitHub 上标星 9000+ 的开源知识库《[二哥的 Java 进阶之路](https://github.com/itwanger/toBeBetterJavaer)》第一版 PDF 终于来了!包括Java基础语法、数组&字符串、OOP、集合框架、Java IO、异常处理、Java 新特性、网络编程、NIO、并发编程、JVM等等,共计 32 万余字,可以说是通俗易懂、风趣幽默……详情戳:[太赞了,GitHub 上标星 9000+ 的 Java 教程](https://javabetter.cn/overview/)
208

沉默王二's avatar
沉默王二 已提交
209 210

微信搜 **沉默王二** 或扫描下方二维码关注二哥的原创公众号沉默王二,回复 **222** 即可免费领取。
211

沉默王二's avatar
沉默王二 已提交
212
![](https://cdn.tobebetterjavaer.com/tobebetterjavaer/images/gongzhonghao.png)