Objects类是一个提供对象基础操作的工具类,其提供的方法包括null-safe或tolerant-safe的对象hashcode计算,toString和比较等。
所在路径:\java\util\Objects.java
一、构造器
Objects类被final修饰,不能被继承。其构造方法直接抛出一个Error,不允许被实例化。
private Objects() {
throw new AssertionError("No java.util.Objects instances for you!");
}
二、equals()
在判断值相等时可以容忍对象为null的情况。
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
相比之下,Object类的equals()方法在自身为null时会抛出nullPointerException。
Object类的equals()方法:
public boolean equals(Object obj) {
return (this == obj);
}
三、deepEquals()
deepEquals()方法实现了两个对象是否相等的深度判断,如果对象是一个数组,则对数组的每一个元素进行比较;如果数组中的每一个元素仍然是object,则对其进行递归的比较。
被比较的任意一个对象为null时返回false而不是继续判断,因此在两对象都为null时只能得到false而不是true。
public static boolean deepEquals(Object a, Object b) {
if (a == b)
return true;
else if (a == null || b == null)
return false;
else
return Arrays.deepEquals0(a, b);
}
Arrays.deepEquals0()方法的源码为:
static boolean deepEquals0(Object e1, Object e2) {
assert e1 != null;
boolean eq;
if (e1 instanceof Object[] && e2 instanceof Object[])
eq = deepEquals ((Object[]) e1, (Object[]) e2);
else if (e1 instanceof byte[] && e2 instanceof byte[])
eq = equals((byte[]) e1, (byte[]) e2);
else if (e1 instanceof short[] && e2 instanceof short[])
eq = equals((short[]) e1, (short[]) e2);
else if (e1 instanceof int[] && e2 instanceof int[])
eq = equals((int[]) e1, (int[]) e2);
else if (e1 instanceof long[] && e2 instanceof long[])
eq = equals((long[]) e1, (long[]) e2);
else if (e1 instanceof char[] && e2 instanceof char[])
eq = equals((char[]) e1, (char[]) e2);
else if (e1 instanceof float[] && e2 instanceof float[])
eq = equals((float[]) e1, (float[]) e2);
else if (e1 instanceof double[] && e2 instanceof double[])
eq = equals((double[]) e1, (double[]) e2);
else if (e1 instanceof boolean[] && e2 instanceof boolean[])
eq = equals((boolean[]) e1, (boolean[]) e2);
else
eq = e1.equals(e2);
return eq;
}
Tips:
1、assert:如果 为true,则程序继续执行。如果为false,则程序抛出AssertionError,并终止执行。
2、assert: <错误信息表达式>:如果 为true,则程序继续执行。如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。
deepEquals()方法的源码为:
public static boolean deepEquals(Object[] a1, Object[] a2) {
if (a1 == a2)
return true;
if (a1 == null || a2==null)
return false;
int length = a1.length;
if (a2.length != length)
return false;
for (int i = 0; i < length; i++) {
Object e1 = a1[i];
Object e2 = a2[i];
if (e1 == e2)
continue;
if (e1 == null)
return false;
// Figure out whether the two elements are equal
boolean eq = deepEquals0(e1, e2);
if (!eq)
return false;
}
return true;
}
四、hashcode()
对象为null时返回0,否则调用Object类的hashcode方法。
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
Object类的hashcode()方法源码为:
public native int hashCode();
五、hash()
为输入序列生成hashcode。此方法返回任意Object序列的hashcode,如果序列过长,int会溢出成负数,但仍然是唯一的。
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
其中Arrays.hashcode()方法的源码为:
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
六、toString()
将toString()方法重写成了如下形式,但最终调用的还是Object类的toString()方法。方法包装的意义在于支持null值,如果入参为null则返回字符串"null"。
public static String toString(Object o) {
return String.valueOf(o);
}
public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}
String.valueOf()方法的源码为:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Object类的toString()方法源码为:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
七、compare()
将普通的compare过程包装了一下。
public static int compare(T a, T b, Comparator super T> c) {
return (a == b) ? 0 : c.compare(a, b);
}
八、requireNonNull()
优雅地判空并在对象为空时抛错。
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.get());
return obj;
}
Supplier是一个接口,可以理解为对象提供者。他是一个函数式编程接口,只有一个get()方法。当程序需要一个对象时,可以通过get()方法来获取。下面是一个使用示例:
public void test(){
// 创建Supplier容器,声明为TestSupplier类型,此时并不会调用对象的构造方法,即不会创建对象
Supplier user = new RobotUser();
// 调用get()方法,此时会调用对象的构造方法,即获得到真正对象
RobotUser user1 = user.get();
}
// 当使用此方法实现get方法时,每次返回的对象都不同
public RobotUser get() {
return new RobotUser();
}
// 当使用此方法实现get方法时,每次返回的对象都相同
RobotUser user = new RobotUser();
public RobotUser get() {
return user;
}
九、isNull()
优雅地判空并返回结果。
public static boolean isNull(Object obj) {
return obj == null;
}
十、nonNull()
优雅地判定非空并返回结果,与isNull()方法相反。
public static boolean nonNull(Object obj) {
return obj != null;
}