JDK 自帶Objects類 方法解析

Objects 對於Object 的關係類似於Collections 對於Collect,十分有意思

----------------------------------------------------------------------------------------------

更新:辛苦碼了這麼多字,結果發現一篇更好的博客,出於良心,文章就成轉載的了


1.Objects 的equals方法

比較兩個對象是否相等,依賴於對象重寫的equals方法(或object 的equals 方法比較地址)

  public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

2.deepEqualsf方法底層調用Arrays類的比較方法,因此一般可以比較 基本數組,如果是對象的話則依賴於對象自身的equals方法

//Objects 類
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 類

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


3.toString 方法 調用String類的valueof 方法,當對象爲null時,輸出“null”,一定程度上防止直接toString的空指針

    public static String toString(Object o) {
        return String.valueOf(o);
    }

//當o爲null時,使用非空默認值
public static String toString(Object o, String nullDefault) {
        return (o != null) ? o.toString() : nullDefault;
    }

4.非空判斷,要求一個對象非空,如果爲空則拋出異常。spring 項目可以使用Asserts.notNull(Obj,message)來斷言,java也有,

甚至你好可以在pom文件中引入

<dependency>
    <groupId>com.google.code.findbugs</groupId>
    <artifactId>jsr305</artifactId>
    <version>3.0.2</version>
</dependency>
<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>15.0</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

直接在虛參聲明中寫@NotNull @NonNul 之類的,讓調用者去做空指針判斷

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

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

發現了一片更好的博客,轉載過來 

https://www.cnblogs.com/quiet-snowy-day/p/6387321.html#label_0

 

Objects 與 Object 區別

Object 是 Java 中所有類的基類,位於java.lang包。

Objects 是 Object 的工具類,位於java.util包。它從jdk1.7開始纔出現,被final修飾不能被繼承,擁有私有的構造函數。

它由一些靜態的實用方法組成,這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的),用於計算對象的hashcode、返回對象的字符串表示形式、比較兩個對象。

 

Objects 各方法介紹與分析

equals

equals方法是判斷兩個對象是否相等。

在比較兩個對象的時候,Object.equals方法容易拋出空指針異常。

——我剛上班的時候,有位老員工教我“字符串常量與變量對象比較的時候,常量要寫在equals外邊,變量放在equals()括號裏邊。” 就是這個原因。

如果是兩個變量比較的時候,就都需要加非空判斷。

* Object.equals方法內調用的是return (this == obj)。String類中是依據字符串內容是否相等來重定義了equals方法。

現在,Objects.equals方法中已經做了非空判斷,所以不會拋出空指針異常,它是null-save空指針安全的,而且也可以簡化代碼。

源碼如下:

    public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

返回目錄

 

 

deepEquals

顧名思義,深度比較兩個對象。

當參數是數組對象,其方法內部採用的是Arrays.deepEquals0方法的算法。

使用Objects.deepEquals方法有個好處,當我們在寫業務代碼時,可以直接使用此方法來判斷兩個複雜類型,

比如使用了泛型的列表對象List<T>、或者通過反射得到的對象,不清楚對象的具體類型。

源碼如下:

複製代碼

    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方法:

     如果參數是Object類型的數組,則調用Arrays.deepEquals方法,在參數數組的循環中,遞歸調用deepEquals0,直到出現不相同的元素,或者循環結束;

     如果參數是基本類型的數組,則根據該類型調用Arrays.equals方法。Arrays工具類依照八種基本類型對equals方法做了重載。

 

返回目錄

 

 

hashCode

返回一個整型數值,表示該對象的哈希碼值。若參數對象爲空,則返回整數0;若不爲空,則直接調用了Object.hashCode方法。

源碼如下:

    public static int hashCode(Object o) {
        return o != null ? o.hashCode() : 0;
    }

Object支持hashCode方法是爲了提高哈希表(例如java.util.Hashtable 提供的哈希表)的性能。

以集合Set爲例,當新加一個對象時,需要判斷現有集合中是否已經存在與此對象相等的對象,如果沒有hashCode()方法,需要將Set進行一次遍歷,並逐一用equals()方法判斷兩個對象是否相等,此種算法時間複雜度爲o(n)。通過藉助於hasCode方法,先計算出即將新加入對象的哈希碼,然後根據哈希算法計算出此對象的位置,直接判斷此位置上是否已有對象即可。

(注:Set的底層用的是Map的原理實現)

 

返回目錄

 

 

hash

爲一系列的輸入值生成哈希碼,該方法的參數是可變參數。

源碼如下:

    public static int hash(Object... values) {
        return Arrays.hashCode(values);
    }

它是將所有的輸入值都放到一個數組,然後調用Arrays.hashCode(Object[])方法來實現哈希碼的生成。

對於當一個對象包含多個成員,重寫Object.hashCode方法時,hash方法非常有用。

舉個Java源碼中的例子:

java.lang.invoke.MemberName 類,該類有Class<?> clazz、String name、Object type、int flags、Object resoulution這幾個成員變量,

該類的hashCode方法如下:

    @Override
    public int hashCode() {
        return Objects.hash(clazz, getReferenceKind(), name, getType());
    }

 警告:當提供的參數是一個對象的引用,返回值不等於該對象引用的散列碼。這個值可以通過調用hashCode方法來計算。

 

返回目錄

 

 

toString

  toString(Object o)

  返回指定對象的字符串表示形式。如果參數爲空對象null,則返回字符串“null”。

  該方法內部調用的是

    return String.valueOf(o);

  String.valueOf(Object obj)方法的內部實現爲

    return (obj == null) ? "null" : obj.toString();

  Object.toString()方法的內部實現爲

    return getClass().getName() + "@" + Integer.toHexString(hashCode());

  toString(Object o, String nullDefault)

  返回指定對象的字符串表示形式。如果參數爲空對象null,則返回第二個參數nullDefault所指定的對象。

返回目錄

 

 

compare

如果兩個參數相同則返回整數0。因此,如果兩個參數都爲空對象null,也是返回整數0。

注意:如果其中一個參數是空對象null,是否會拋出空指針異常NullPointerException取決於排序策略,如果有的話,則由Comparator來決定空值null。

源碼如下:

    public static <T> int compare(T a, T b, Comparator<? super T> c) {
        return (a == b) ? 0 :  c.compare(a, b);
    }

返回目錄

 

 

requireNonNull

  requireNonNull(T obj)

  檢查指定類型的對象引用不爲空null。當參數爲null時,拋出空指針異常。設計這個方法主要是爲了在方法、構造函數中做參數校驗。

  源碼如下:

    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

  舉個例子:

  當我們通過帶參的構造函數創建對象時,創建對象的同時就可以進行參數校驗。同時也簡化了很多代碼。

     public class Foo {
          public Foo(Bar bar) {
               this.bar = Objects.requireNonNull(bar);
          }
     }

 

  requireNonNull(T obj, String message) 

  該方法是requireNonNull的重載方法,當被校驗的參數爲null時,根據第二個參數message拋出自定義的異常消息。

  源碼如下:

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

 

  requireNonNull(T obj, Supplier<String> messageSupplier)

  檢查指定的對象引用不爲空null,如果是空,拋出自定義的空指針異常。從jdk1.8開始。

  與requireNonNull(Object, String)方法不同,本方法允許將消息的創建延遲,直到空檢查結束之後。

  雖然在非空例子中這可能會帶來性能優勢, 但是決定調用本方法時應該小心,創建message supplier的開銷低於直接創建字符串消息。  

  源碼如下:

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

 

isNull

判空方法,如果參數爲空則返回true。從jdk1.8開始。

源碼如下:

    public static boolean isNull(Object obj) {
        return obj == null;
    }

apiNote: 該方法的存在是用於java.util.function.Predicate類,filter(Objects::isNull)。

來看下Predicate類中,使用到本方法的代碼: 

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)  
                ? Objects::isNull   // 雙冒號,代表方法引用。
                : object -> targetRef.equals(object); // 此處爲lambda表達式。接收object對象,返回參數targetRef與該對象的比較結果。
    }

 

 

nonNull

判斷非空方法,如果參數不爲空則返回true。從jdk1.8開始。

源碼如下:

    public static boolean nonNull(Object obj) {
        return obj != null;
    }

apiNote: 該方法的存在是用於java.util.function.Predicate類,filter(Objects::nonNull)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章