Java判等問題:細節決定成敗

判等問題,在我們代碼中就是一句話的事情,但是這一行代碼如果處理不好,不僅會出現緻命的bug,下面我們就以Java中 equals、compareTo 和 Java 的數值緩存、字元串駐留等問題展開讨論
1. 注意 equals 和 == 的差別
在業務代碼中,我們通常使用 equals 或 == 進行判等操作。equals是方法而 ==是操作符
: 1.對基本類型,比如 int 、long、進行判斷,隻能使用 == ,比較對是直接值,因為基本類型對值就是其數值
: 2.對引用類型,比如Integer 、Long 和 String 進行判等,需要使用 equals 進行内容判等。因為引用類型,需要使用equals進行内容判等。因為飲用類型等直接值是指針,使用 == 的話,比較的是指針,也就是兩個對象在記憶體中的位址,即比較他們是不是同一個對象,而不是比較對象内容
結論:
- 比較值的内容,除了基本類型隻能使用 ==外,其他類型都需要使用 equals。
案例:
public static void main(String[] args) throws Exception {
Integer a = 127;
Integer b = 127;
System.out.println(" a == b " +(a == b));
Integer c = 128;
Integer d = 128;
System.out.println(" c == d " + (c == d));
Integer g = new Integer(127);
Integer h = new Integer(127);
System.out.println(" g == h " + (g == h));
Integer i = 128;
int j = 128;
System.out.println(" i == j " + (i == j));
}
結果 :
a == b true
c == d false
g == h false
i == j true
- 在 a == b 中,編譯器會把 a = 127 轉換為 Integer.valueOf(127),源碼可以發現,這個轉換是内部其實做了緩存,使得兩個 Integer 指向同一個對象 是以傳回true
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
- 在 c == d 中使用128 傳回false ,Integer 當不符合-128 127值範圍時候。記住用的:new,開辟新的記憶體空間,不屬于IntergerCache管理區
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
-
在g == h案例中,New 出來的 Integer 始終是不走緩存的新對象。比較兩個新對象,
或者比較一個新對象和一個來自緩存的對象,結果肯定不是相同的對象,是以傳回 false。
2. equals 沒有這麼簡單
如果看過 Object 類源碼,你可能就知道,equals 的實作其實是比較對象引用:
public boolean equals(Object obj) {
return (this == obj);
}
重點(注意點):
- 不重寫equals方法與“ == ”一樣,用于比較對象的引用是否相等。
之是以 Integer 或 String 能通過 equals 實作内容判等,是因為它們都重寫了這個方法。
String 的 equals 的實作:
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Integer.equals.()
/**
* Compares this object to the specified object. The result is
* {@code true} if and only if the argument is not
* {@code null} and is an {@code Integer} object that
* contains the same {@code int} value as this object.
*
* @param obj the object to compare with.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
個人部落格位址:
http://blog.yanxiaolong.cn/