天天看點

java.util.Objects 源碼學習

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

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

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

<a></a>

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

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

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

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

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

java.util.Objects 源碼學習

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

源碼如下:

<a href="http://www.cnblogs.com/quiet-snowy-day/p/6387321.html#label_0" target="_blank">傳回目錄</a>

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

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

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

比如使用了泛型的清單對象List&lt;T&gt;、或者通過反射得到的對象,不清楚對象的具體類型。

 簡短的說明下Arrays.deepEquals0方法:

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

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

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

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

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

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

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

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

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

舉個Java源碼中的例子:

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

該類的hashCode方法如下:

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

  傳回指定對象的字元串表示形式。如果參數為空對象null,則傳回字元串“null”。

  該方法内部調用的是

    return String.valueOf(o);

  String.valueOf(Object obj)方法的内部實作為

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

  Object.toString()方法的内部實作為

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

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

如果兩個參數相同則傳回整數0。是以,如果兩個參數都為空對象null,也是傳回整數0。

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

  requireNonNull(T obj)

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

  源碼如下:

  舉個例子:

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

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

  源碼如下:

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

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

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

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

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

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

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

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

本文轉自帥氣的頭頭部落格51CTO部落格,原文連結http://blog.51cto.com/12902932/1924601如需轉載請自行聯系原作者

sshpp