Java 中的 Objects 类是在 JDK 7 中引入的工具类,位于 java.util 包中。Objects 类提供了一些静态方法,用于操作对象,主要涉及以下几个方面:
equals(obj1, obj2):用于比较两个对象是否相等。它会首先检查两个对象引用是否相同,如果相同则返回 true。如果任一对象为 null,则返回 false。否则,调用 obj1.equals(obj2) 方法来比较对象的内容。
hashCode(obj):用于计算对象的哈希码。如果 obj 为 null,则返回 0。否则,调用 obj.hashCode() 方法来计算对象的哈希码。
toString(obj):将对象转换为字符串表示。如果 obj 为 null,则返回 "null"。否则,调用 obj.toString() 方法将对象转换为字符串。
requireNonNull(obj[, message]):用于检查对象是否为 null。如果 obj 为 null,则抛出 NullPointerException 异常;否则,返回 obj。可选参数 message 用于指定自定义异常消息。requireNonNull:
public static T requireNonNull(T obj)
public static T requireNonNull(T obj, String message)
public static T requireNonNull(T obj, SuppliermessageSupplier)
messageSupplier - 如果抛出 NullPointerException ,将使用详细消息的供应商 (可以描述具体哪个对象发生了空指针)
作用:检查指定的对象引用是否为null,如果是,则抛出自定义的NullPointerException
public static T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
public static T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
public static T requireNonNull(T obj, Supplier messageSupplier) {
if (obj == null)
throw new NullPointerException(messageSupplier == null ?
null : messageSupplier.get());
return obj;
}
isNull(obj):用于检查对象是否为 null。如果 obj 为 null,则返回 true;否则,返回 false。
nonNull(obj):用于检查对象是否不为 null。如果 obj 不为 null,则返回 true;否则,返回 false。
Objects 类的主要目的是提供了一些常用的操作对象的静态方法,可以避免在处理对象时出现空指针异常和增加代码的可读性。它提供了对对象比较、哈希码计算、转换为字符串以及非空检查等常见操作的统一封装。
需要注意的是,Objects 类的方法都是静态方法,可以直接通过类名调用,无需创建对象实例。
Java 的 Object 类和 Objects 类在功能和使用方式上有一些区别。
Object 类是 Java 中所有类的根类,它定义了一些通用的方法,比如 equals()、hashCode()、toString() 等。每个类都会隐式继承 Object 类的基本功能。可以通过扩展 Object 类来创建新的类。Objects 类是在 JDK 7 中引入的实用工具类,包含一些常用的静态方法。
Object 类的方法是被所有对象继承和使用的,例如,每个对象都可以直接调用 equals()
、hashCode()
、toString()
等方法。而 Objects 类的方法是通过类名直接调用的静态方法,例如 Objects.equals()
、Objects.hashCode()
、Objects.toString()
等。
Object 类的方法对于自定义类需要进行重写和实现,以便根据实际需求提供相应的功能。Objects 类的方法则提供了一些通用的操作,如空值检查、比较、哈希码计算等,可以直接调用,无需继承或重写。
Object 类提供了一些基本的方法,如 clone()
、getClass()
、notify()
、wait()
等,用于对象的克隆、类的反射操作、线程的同步等。Objects 类主要关注对象的比较、哈希码计算、空值检查和对象转换等常用的操作。
总之,Object 类是所有类的基类,提供了一些通用的功能,需要根据实际需求进行重写和实现;而 Objects 类是一个实用工具类,提供了一些静态方法,用于执行一些常见的对象操作,不需要对象的继承和重写。在实际开发中,根据需要选择合适的类和方法来操作对象。
Objects 是 Object 的工具类,位于java.util包,由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode、返回对象的字符串表示形式、比较两个对象。
import java.util.Objects;
public class Exam11_22 {
public static void main(String[] args) {
Object o = new Object();
System.out.println("空对象与非空对象比较1:"+Objects.equals(o, null));
System.out.println("空对象与非空对象比较2:"+Objects.equals(null, o));
System.out.println("非空对象的哈希码1:"+Objects.hashCode(o));
System.out.println("非空对象的哈希码2:"+o.hashCode());
System.out.println("空对象的哈希码:"+Objects.hashCode(null));
System.out.println("非空对象转为字符串1:"+Objects.toString(o));
System.out.println("非空对象转为字符串2:"+o.toString());
System.out.println("空对象转为字符串默认值:"+Objects.toString(null));
System.out.println("设定空对象转为字符串的值:"+Objects.toString(null, "对象为空"));//①
}
}
从图11-22可以看出:对于非空对象求哈希码以及转换为字符串的操作,使用Objects类所定义的方法和使用Object类所定义的方法完成都有相同的效果。而对于空对象而言,求哈希码以及转换字符串的操作不会出现空指针异常,而是采取了特殊的处理方式。在默认情况下,以数字0作为空对象的哈希码,而以“null”当做空对象转换为字符串的结果。如果程序员不希望以“null”当做空对象转换为字符串的结果,还可以自行设置,例如语句①就把空对象转换为字符串的结果设置为“对象为空”。而调用Objects类的equals()方法对两个对象进行比较时,无论是否有空对象,也无论空对象作为方法的第几个参数都不会出现空指针异常。
Objects类中除了提供有不产生空指针异常的equals()、hashCode()和toString()方法外,还提供了一个用于比较数组元素的deepEquals()方法,这个方法能够深入数组内部比较两个数组的每一对元素是否对应相同。下面的【例11_23】展示了deepEquals()方法的运行效果。
import java.util.Objects;
public class Exam11_23 {
public static void main(String[] args) {
String[] s1 = new String[]{"1","2","3"};
String[] s2 = new String[]{"1","2","3"};
System.out.println("使用equals()方法比较s1与s2:"+ Objects.equals(s1,s2));
System.out.println("使用deepEquals()方法比较s1与s2:"+ Objects.deepEquals(s1,s2));
System.out.println("使用equals()方法比较s1[0]与s2[0]:"+ Objects.equals(s1[0],s2[0]));
System.out.print("使用deepEquals()方法比较s1[0]与s2[0]:");
System.out.println(Objects.deepEquals(s1[0],s2[0]));
}
}
从图11-23可以看出:使用equals()方法比较数组s1和s2的结果为false,这是因为数组也是对象,equals()方法在比较数组时只判断这两个数组是不是同一个对象,并不会深入到数组内部去比较每一对元素是否对应相同。而deepEquals()方法则不同,它会深入数组内部依次比较对应位置上的两个元素是否都相同,因此deepEquals()方法比较s1和s2的结果为true。如果被比较的不是数组而是普通对象,则equals()方法和deepEquals()方法的运行效果完全相同。本例中分别使用equals()方法和deepEquals()比较s1和s2的首个元素,比较的结果都是true。
import java.util.Objects;
public class Exam11_24 {
public static void main(String[] args) {
String str1 = null;
String str2 = "ABCDE";
int[] array = {1,2,3,4,5};
//检验str1是否为空
Objects.requireNonNull(str1);
str1.charAt(2);//①
//检验2和8是否是截取字符串str2的合理参数
Objects.checkFromToIndex(2,8,str2.length());
str2.substring(2,8);//②
//检验10是否是数组array的合理下标
Objects.checkIndex(10,array.length);
int a = array[10];//③
}
}
语句①调用了str1的charAt()方法,在调用这个方法之前先检验了str1是否为空对象。语句②调用str2的substring()方法截取字符串,在调用方法前先检验了参数2和8是否在合理范围内。语句③取出数组array下标为10的元素,在取出之前也检验了下标值是否合理。通过观察程序不难发现,语句①会因str1为空而抛出空指针异常,而语句②和③都会因参数数值不合理导致抛出数组越界异常。而这三条语句之前的检验就会提前发现数据的不合理性,并且以抛出异常的形式通知程序员语句①、②、③运行不会成功。虽然在不检验数据合理性的情况下语句①、②、③也会抛出同样的异常,但这样的检验也是有意义的,这是因为在语句①、②、③真正执行前就已经发现了数据的不合理性,这样就不会造成关键代码运行产生错误的结果。需要提醒各位读者:【例11_24】的程序代码中能够造成3个异常,但因为一旦抛出异常程序就会中止运行,所以实际运行程序时只会出现1个异常。