java
public final class Objects {...}
未標註繼承與實現,可是默認繼承Object類。數組
此方法用於比較a,b兩個對象若是a,b兩個對象指向同一引用地址,返回0;不然調用c的compare方法進行比較,cd的compare方法中傳入的兩個參數就分別是a,b。 源代碼:ide
public static <T> int compare(T a, T b, Comparator<? super T> c) {
return (a == b) ? 0 : c.compare(a, b);
}
測試代碼:函數
public class Demo1 implements Comparator<Demo1> {
private String data;
public Demo1() {
}
public Demo1(String data) {
this.data = data;
}
public static void main(String[] args) {
Demo1 test1 = new Demo1("測試代碼Test1");
Demo1 test2 = new Demo1("測試代碼Test2");
Demo1 test3 = new Demo1("測試代碼Test1");
int a = Objects.compare(test1, test1, new Demo1());
System.out.println(a);
int b = Objects.compare(test1, test3, new Demo1());
System.out.println(b);
int c = Objects.compare(test1, test2, new Demo1());
System.out.println(c);
}
此方法用於比較a,b兩個對象是否深度相等,爲何要叫深度相等?由於a,b兩個對象均可覺得數組。因爲Java中Object類是一切類的基類,因此Object o = new Object[10]的代碼是被容許的。因此傳入的對象能夠是一個數組。若是傳入的對象是數組,要比較兩個對象是否深度相等,就要比較兩個數組對應下標的元素是否都相等。若是傳入的對象有一個不是數組,就直接調用a對象的equals方法傳入b對象比較兩對象是否相等。 下面咱們來看下源碼:工具
public static boolean deepEquals(Object a, Object b) {
//若是a和b指向同一地址,則a和b是同一對象,返回true。
if (a == b)
return true;
//若是a或b中有一對象爲空,則a和b不是同一類型對象,返回false。這樣也避免了當a爲空或者b爲空時調用equals方法形成的空指針引用異常。
else if (a == null || b == null)
return false;
//不然,調用Arrays類的deepEquals0方法對a,b進行深度比較。
else
return Arrays.deepEquals0(a, b);
}
咱們跳到Arrays類的deepEquals0方法進行分析,雖然有不少的判斷語句,可是邏輯基本相同,咱們就分析其中幾個:性能
static boolean deepEquals0(Object e1, Object e2) {
//由於以後要調用e1的equals方法,因此e1不能爲空。
assert e1 != null;
//定義返回值。
boolean eq;
//這個if是用於判斷引用數據類型數組的,若是e1,e2都是引用數據類型數組的話,就調用Arrays類的deepEquals方法判斷兩數組是否相等。以後的基本數據類型的判斷流程也同樣。
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);
//若是e1和e2不全爲數組,就調用e1的equals方法。
else
eq = e1.equals(e2);
//返回判斷的結果。
return eq;
}
Arrays類的deepEquals方法測試
public static boolean deepEquals(Object[] a1, Object[] a2) {
//若是傳入的兩數組指向同一地址,則是同一對象,返回true。
if (a1 == a2)
return true;
//若是a1或a2中有一對象爲空,則a1和a2不是同一類型對象,返回false。這樣也避免了當a1爲空或者a2爲空時調用equals方法形成的空指針引用異常。
if (a1 == null || a2==null)
return false;
int length = a1.length;
//判斷a1或a2的長度是否相等,不相等則顯然不能比較,返回false。
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;
//e1爲空,不是同一對象,返回false。
if (e1 == null)
return false;
// Figure out whether the two elements are equal
//再次對數組中e1,e2元素進行深度比較,而不是直接調用e1的equals方法,避免e1或e2仍是數組致使誤判。
boolean eq = deepEquals0(e1, e2);
//若是e1與e2比較返回的是false,則a1,a2不相等,返回false。
if (!eq)
return false;
}
//比較完畢,沒有不相等的元素,返回true。
return true;
}
測試代碼:ui
public static void main(String[] args) {
Object[] o1 = {1, "String", 'c', 1.0, false};
Object o11 = o1;
Object[] o2 = {1, "String", 'c', 1.0, false};
Object o22 = o2;
Object[] o3 = {1, "String", 'c', 1.0, true};
Object o33 = o3;
System.out.println(Objects.deepEquals(o11, o11));
System.out.println(Objects.deepEquals(o11, o22));
System.out.println(Objects.deepEquals(o11, o33));
Object[] o4 = {o11, o11};
Object[] o5 = {o11, o22};
Object[] o6 = {o11, o33};
System.out.println(Objects.deepEquals(o4, o4));
System.out.println(Objects.deepEquals(o4, o5));
System.out.println(Objects.deepEquals(o4, o6));
}
判斷兩對象是否相等,相比直接調用其中一對象的equals方法,a != null避免了空指針引用異常,相等返回true,不等返回false。 源代碼:this
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
獲得一列對象的hashcode,使用了Arrays.hashCode(Object[])方法,Object[]數組元素就是hash方法傳入的參數值,這裏的values實際上是一個Object數組。Object... values的參數寫法表示傳入的Object對象不限制數量。 源代碼:atom
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
獲取一個對象的hashCode。 源代碼:
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
判斷對象是否爲空,爲空返回true,不爲空返回false。 源代碼:
public static boolean isNull(Object obj) {
return obj == null;
}
判斷對象是否爲不爲空,不爲空返回true,爲空返回false。 源代碼:
public static boolean nonNull(Object obj) {
return obj != null;
}
私有的構造方法,必定拋出斷言錯誤:「沒有適合您的java.util.Objects實例!」 源代碼:
private Objects() {
throw new AssertionError("No java.util.Objects instances for you!");
}
檢查指定的對象引用是否不是null,是null則拋出空指針異常,不然返回傳入的對象。此方法主要用於在方法和構造函數中進行參數驗證,以下所示:
public Foo(Bar bar) {
this.bar = Objects.requireNonNull(bar);
}
源代碼:
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
檢查指定的對象引用是否不是null,是null則拋出空指針異常並將第二個參數的字符串值寫在異常信息中,不然返回傳入的對象。此方法主要用於在方法和構造函數中進行參數驗證,以下所示:
public Foo(Bar bar, Baz baz) {
this.bar = Objects.requireNonNull(bar, "bar must not be null");
this.baz = Objects.requireNonNull(baz, "baz must not be null");
}
源代碼:
public static <T> T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
檢查指定的對象引用是否爲null ,若是是,則拋出自定義的NullPointerException。與方法requireNonNull(Object, String)不一樣,此方法容許建立要延遲的消息,直到進行空檢查。 雖然這能夠在非空狀況下賦予性能優點,但在決定調用此方法時,應注意建立消息提供者的成本小於僅直接建立字符串消息的成本。 源代碼:
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) {
if (obj == null)
throw new NullPointerException(messageSupplier.get());
return obj;
}
返回傳入對象o的toString方法返回的字符串,若是傳入對象爲空,返回"null"字符串。 源代碼:
public static String toString(Object o) {
return String.valueOf(o);
}
若是傳入對象非空,返回該對象的toString方法返回的字符串,不然返回自定義的信息。 源代碼:
public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}