美文网首页
Objects类源码笔记

Objects类源码笔记

作者: LuckyBuzz | 来源:发表于2020-04-13 14:37 被阅读0次

    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 <boolean表达式>:如果<boolean表达式>为true,则程序继续执行。如果为false,则程序抛出AssertionError,并终止执行。
    2、assert <boolean表达式> : <错误信息表达式>:如果<boolean表达式>为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 <T> int compare(T a, T b, Comparator<? super T> c) {
        return (a == b) ? 0 :  c.compare(a, b);
    }
    

    八、requireNonNull()

    优雅地判空并在对象为空时抛错。

    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }
    
    public static <T> T requireNonNull(T obj, String message) {
        if (obj == null)
            throw new NullPointerException(message);
        return obj;
    }
    
    public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
        if (obj == null)
            throw new NullPointerException(messageSupplier.get());
        return obj;
    }
    

    Supplier是一个接口,可以理解为对象提供者。他是一个函数式编程接口,只有一个get()方法。当程序需要一个对象时,可以通过get()方法来获取。下面是一个使用示例:

    public void test(){    
        // 创建Supplier容器,声明为TestSupplier类型,此时并不会调用对象的构造方法,即不会创建对象
        Supplier<RobotUser> 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类源码笔记

          本文链接:https://www.haomeiwen.com/subject/tgigmhtx.html