Objects类源码笔记

Objects类是一个提供对象基础操作的工具类,其提供的方法包括null-safe或tolerant-safe的对象hashcode计算,toString和比较等。
所在路径:\java\util\Objects.java

Objects类结构

一、构造器

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 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;
}

你可能感兴趣的:(Objects类源码笔记)