new和malloc的區別,Java中equals與==的區別(全面)

 2023-12-09 阅读 29 评论 0

摘要:Java中equals與 == 的區別是什么呢?關于這個問題的回答大家都聽說過,==是比較引用是否相同,equals是比較值是否相等。 這個答案對,但是不全面。new和malloc的區別、引用是否相同其實就是它們指向的地址是否為同一個。 下面舉一些
Java中equals與 == 的區別是什么呢?關于這個問題的回答大家都聽說過,==是比較引用是否相同,equals是比較值是否相等。

這個答案對,但是不全面。new和malloc的區別、引用是否相同其實就是它們指向的地址是否為同一個。

下面舉一些例子:
String source="abc";
String str1 = "abc";
String str2 = new String(source);
String str3 = new String("abc");
String str4 = source;
String str5="ab"+"c";
System.out.println(source == str1);//1
System.out.println(source == str2);//2
System.out.println(source == str3);//3
System.out.println(source == str4);//4
System.out.println(source == str5);//5
請問:下面5條打印什么結果?最好自己先想一下再看結果。Java replace。









結果為:true
? ??? ??? ? ?false
? ??? ??? ???false
? ??? ??? ? ?true
? ??? ??? ? ?true



好的,容我一一解釋。
1打印true 是因為Java中有一個字符串池,Java會緩存所用過的字符串變量,例如:執行String a ?= "Java";語句之后,
系統的字符串池中就會緩存一個字符串“Java”;如果程序再次執行String b = "Java"后,系統將會讓
b直接指向字符串池中的"Java"字符串,因此a==b將會返回true。
記住這一點==是比較引用是否相同"就不難理解。因為它們都指向了同一塊內存。

2打印false因為?str2 = new String(source); 通過new調用了String類構造器方法創建了一個對象,并將它的引用賦值給了str2 變量。
所以會有兩個內容為"abc"的對象,分別通過source與str2引用。

3打印false原因見上一條。

4打印true就很好理解了,str4 = source;就是讓str4指向source引用的對象,它們引用的都是同一個地址。


5打印true讓我展開來講一下

String str1 = "abc";
String str2 = "abcabc";
String str3 = str1+str1;
String str4 = "abc"+"abc";
final String str5 = "abc";
String str6 = str5+str5;
System.out.println(str2==str3);//6
System.out.println(str2==str4);//7
System.out.println(str2==str6);//8
結果為:
false
true
true
6 ?str3,它是由str1+str1得到,由于str1只是個普通變量,因此
編譯器無法在編譯時確定str3的值,不會讓str3指向字符串池中緩存中的“abcabc”,所以false.


7 str4的值是兩個字符串直接進行連接運算,由于編譯器可以在編譯階段就確定str4的值為“abcabc”,所以
系統會讓str4直接指向字符串池中緩存中的“abcabc”字符串。所以true。

8?對于final實例變量而言,只有在定義該變量時指定初始值才會有“宏變量”的效果。此處正好符合要求,
所以編譯器會對str5進行“宏替換”,可以在編譯階段就確定str6的值為“abcabc",因此為;true。

?由 7,8 得,str4 = "abc"+"abc"; 編譯器可以在編譯階段就確定str4的值,也就是直接字符串拼接等同于宏變量替換。

對兩個內容相等的String 變量進行equals判斷,結果為true。沒有什么好講的了。

String 字符串池以及==問題就講到這里。



接下來講非String對象的==與equals問題

Integer i1 = 5;
Integer i2 = 5;
System.out.println(i1+"=="+i2+":"+(i1==i2));
i1 = 128;
i2 = 128;
System.out.println(i1+"=="+i2+":"+(i1==i2));
i1 = 127;
i2 = 127;
System.out.println(i1+"=="+i2+":"+(i1==i2));
i1 = -128;
i2 = -128;
System.out.println(i1+"=="+i2+":"+(i1==i2));
i1 = -129;
i2 = -129;
System.out.println(i1+"=="+i2+":"+(i1==i2));
結果:

5==5:true
128==128:false
127==127:true
-128==-128:true
-129==-129:false
當我們給Integer賦值時,實際上調用了Integer.valueOf(int)方法,查看源碼,其實現如下:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache實現如下:
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) {
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);
}
high = h;
?
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
?
private IntegerCache() {}
}
總之,如果范圍[-128,127]的整數,會使用Integer常量池。所以==返回true,不在這個范圍:? return new Integer(i); 所以為false

另外:Java的8種基本類型(Byte, Short, Integer, Long, Character, Boolean, Float, Double), 除Float和Double(小數)以外, 其它六種都實現了常量池, 但是它們只在大于等于-128并且小于等于127時才使用常量池。

Integer int1 = 12911;
Integer int2 = 12911;
System.out.println(int1.equals(int2));//true
所以,同一基本類型之間的比較最好用equals。
但是,不同基本類型之間呢,比如short和Integer呢
Integer i = 1;
short s = 1;
System.out.println(i.equals(s));//false
System.out.println(i == s);//true
為什么。看源碼:
Integer.class的源碼
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

if (obj instanceof Integer) {
}
return false;

就是說如果參數obj不是Integer的實例,就會返回false。

先寫到這里,果然好累。

參考:
http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html

http://blog.csdn.net/shw2004/article/details/5678703

<Java瘋狂編程>系統 李剛著






版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/193822.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息