好用的java.util.Objects
類
在jdk1.7中,新增了一個工具類,就是java.util.Objects
類。它有3個簡單的封裝方法,對於平常的使用來說挺有用的,分別是:hashCode
、equals
、toString
這3個方法。
1、hashcode生成
// 1. Objects.hash(Object... values)
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
// 2. Arrays.hashCode(Object a[])
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;
}
// 3. Object.hashCode()
public native int hashCode();
首先,Objects的hash方法接收可變引數,可變引數的內部是一個陣列。然後內部呼叫Arrays的hashCode方法,我們來看一下其方法:核心是遍歷每一個引數來計算result值,在計算的過程中,每一個引數上轉型為Object使用hashCode來生成隨機值。那麼Object的hashCode又是什麼?這是一個本地方法,原始碼不給出實現,其數值和物件的記憶體地址有關。
引數雖然上轉型為Object,但是對於String、Integer等物件型別,它們都重寫了hashCode方法。因為是基於記憶體地址的生成,所以不同物件生成的hashcode值衝突的機率是很小的。
2、物件equals比較
// 1. Objects.equals(Object a, Object b)
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
// 2. Object.equals(Object obj)
public boolean equals(Object obj) {
return (this == obj);
}
首先是物件的引用判斷,其次就是呼叫物件自身的equals方法來比較,如果物件型別沒有重寫equals的話,就會呼叫Object的equals方法(仍然是物件的引用比較)。
事實上,我們進行equals比較的物件,除了引用物件之外,就是String、Integer(自動裝箱後)等型別了。
對於String,直接進行引用比較。而對於Integer、Double等物件型別,它們都重寫了equals方法,貼出Integer的equals方法:
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
可以看到,內部是進行值相等判斷。
hashCode與equals方法的重要性
對於雜湊結構(hash)的集合型別,比如說HashMap、HashSet等,如果我們用它們來儲存我們自定義的物件,那麼我們就必要重寫類的hashCode與equals方法。<u>為什麼要重寫,這個原因就不贅述了。</u> 還有Set集合類,由於它儲存不重複的元素。
下面我們給出利用Objects工具類的一種較為簡單實用的重寫方式:
public class Building {
private String name;
private double area;
@Override
public int hashCode() {
return Objects.hash(name, area);
}
@Override
public boolean equals(Object obj) {
// 引用相等判斷
if (obj == this) {
return true;
}
// 型別判斷
if (!(obj instanceof Building)) {
return false;
}
Building building = (Building) obj;
// 關鍵域相等判斷
// 基本型別不要用用Objects.equals()方法,會自動裝箱帶來額外開銷
return Objects.equals(name, building.name) && (area == building.area);
}
@Override
public String toString() {
return Objects.toString("name = " + name, "name is undefined") + ", "
+ Objects.toString("area = " + area, "area is undefined");
}
// setter、getter
}
3、toString
我們自己重寫toString方法時,有一點比較難寫,就是預設值設定。
// Objects.toString(Object o, String nullDefault)
public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}
// Objects.toStirng(Object 0)
public static String toString(Object o) {
return String.valueOf(o);
}
我們在重寫toString時,可以參考上面的Building
類的寫法。