新聞中心
equal和==
== 比較的是變量(棧)內(nèi)存中存放的對(duì)象的(堆)內(nèi)存地址,用來判斷兩個(gè)對(duì)象的地址是否相同,即是否是指相同一個(gè)對(duì)象。比較的是真正意義上的指針操作。

路橋網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,路橋網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為路橋上1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營銷網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的路橋做網(wǎng)站的公司定做!
equals用來比較的是兩個(gè)對(duì)象的內(nèi)容是否相等,由于所有的類都是繼承自java.lang.Object類的,所以適用于所有對(duì)象,如果沒有對(duì)該方法進(jìn)行覆蓋的話,調(diào)用的仍然是Object類中的方法,而Object中的equals方法返回的卻是==的判斷。
基本數(shù)據(jù)類型
byte,short,char,int,long,float,double,boolean基本數(shù)據(jù)類型之間的比較需要用雙等號(hào)(==),因?yàn)樗麄儽容^的是值。
引用數(shù)據(jù)類型
接口、類、數(shù)組等非基本數(shù)據(jù)類型,Java中的字符串String屬于引用數(shù)據(jù)類型。
當(dāng)他們用(==)進(jìn)行比較的時(shí)候,比較的是他們?cè)趦?nèi)存中的存放地址,所以,除非是同一個(gè)new出來的對(duì)象,他們的比較后的結(jié)果為true,否則比較后結(jié)果為false。因?yàn)闆]new一次就會(huì)重新開辟一個(gè)新的堆內(nèi)存空間。
Java中的==
==
Java中的==表示的是什么呢?有時(shí)候很令人費(fèi)解。比如,以下例子輸出是什么?
// 例一
String str = "wo";
String str1 = "wo";
System.out.println("例一:" + (str == str1));
// 例二
String str2 = new String("wo");
String str3 = new String("wo");
System.out.println("例二:" + (str2 == str3));
// 例三
int i1 = 1;
int i2 = 1;
System.out.println("例三:" + (i1 == i2));
// 例四
TestObject t1 = new TestObject();
TestObject t2 = new TestObject();
System.out.println("例四:" + (t1 == t2));最終結(jié)果如下:
例一:true
例二:false
例三:true
例四:false在Java中,如果是基本數(shù)據(jù)類型,則 == 比較的是值;如果是對(duì)象類型,則 == 比較的是對(duì)象的地址。但是,有時(shí)候會(huì)疑惑,String不是對(duì)象類型么?為什么例一是true呢?這個(gè)就要談?wù)勛址A砍氐膯栴}。
字符串常量池
String類是我們平常項(xiàng)目中使用頻率非常高的一種對(duì)象類型,JVM為了提升性能和減少開銷,避免字符串的重復(fù)創(chuàng)建,維護(hù)了一塊特殊的內(nèi)存空間,即字符串常量池。當(dāng)需要使用字符串時(shí),先去字符串常量池查看該字符串是否已經(jīng)存在,如果存在,則可直接使用;如果不存在,初始化,并將該字符串放入到字符串常量池中。
「注意」:在JDK1.6及之前版本,字符串常量池在方法區(qū)中 在JDK1.7及以后版本,字符串常量池移到了堆中。
使用String str="wo",可能創(chuàng)建一個(gè)或者不創(chuàng)建對(duì)象。如果“wo”在字符串常量池中已經(jīng)存在,則不會(huì)再創(chuàng)建String類型的值為“wo”的對(duì)象,而是將str指向這個(gè)“wo”對(duì)象內(nèi)存地址,后續(xù)無論用這種方式創(chuàng)建多少個(gè)指向“wo”的引用,在內(nèi)存中,都只有一個(gè)“wo”內(nèi)存地址被分配。而==判斷的是對(duì)象內(nèi)存的地址,所以例一返回true。下圖是用這種方式創(chuàng)建字符串的示例圖。
圖片
對(duì)象存放在堆中,字符串常量池是堆中一塊特殊區(qū)域,new出來的是對(duì)象,字符串可以通過直接賦值創(chuàng)建一個(gè)對(duì)象,如上所述。對(duì)象的引用存放在棧中,String str是對(duì)象的引用。
在上圖中,棧存放的是字符串的引用,str和str1存放的都是對(duì)象“wo”的內(nèi)存地址,==判斷對(duì)象時(shí),判斷的是他們存儲(chǔ)的內(nèi)存地址是否相同,由上圖可見,他們的內(nèi)存地址是相同的,所以例一輸出的是true。
圖片
例二的兩個(gè)字符串都是通過new的方式創(chuàng)建對(duì)象的,所以在堆上有兩個(gè)String對(duì)象,且這兩個(gè)對(duì)象指向字符串常量池中的同一個(gè)對(duì)象“wo”,如上圖所示,此時(shí)str2和str3存儲(chǔ)的對(duì)象地址就不相同,所以例二返回的是false。
String str = new String("wo")創(chuàng)建了幾個(gè)對(duì)象?如果字符串常量池中沒有“wo”,則該句創(chuàng)建了兩個(gè)對(duì)象,首先會(huì)創(chuàng)建一個(gè)“wo”存放在字符串常量池中,其本身就是一個(gè)對(duì)象;然后會(huì)new 一個(gè)字符串對(duì)象,并將“wo”的引用返回給new出來的對(duì)象;如果字符串常量池中有“wo”,則該句只創(chuàng)建了一個(gè)對(duì)象,因?yàn)樵摼涫紫葧?huì)查找字符串常量池中是否存在“wo”,如果存在則直接返回"wo"的引用給new出來的對(duì)象。
總結(jié)
- 如果是基本數(shù)據(jù)類型,==判斷的是值。
- 如果是對(duì)象類型,==判斷的是對(duì)象的地址。
- 通過直接賦值而不是new的方式給String賦值,如果字符串常量池中有該對(duì)象,則不會(huì)再創(chuàng)建,此時(shí)通過 == 判斷,返回的是true。如:String str="wo";String str1="wo";str == str1為true。
- 在JDK1.6及以前版本,字符串常量池在方法區(qū)中;在JDK1.7及以后,字符串常量池在堆中。
- 對(duì)象的引用保存在棧中。
Java中equals()
Java中所有的類都是繼承與Object這個(gè)基類的,在Object類中定義了一個(gè)equals方法,這個(gè)方法的初始行為是比較對(duì)象的內(nèi)存地址,但在一些類庫中已經(jīng)重寫了這個(gè)方法(一般都是用來比較對(duì)象的成員變量值是否相同),比如:String,Integer,Date 等類中,所以他們不再是比較類在堆中的地址。
public boolean equals(Object var1) {
return this == var1;
}String類的equals()方法
String類中重寫后的代碼:
public boolean equals(Object var1) {
if (this == var1) {
return true;
} else {
if (var1 instanceof String) {
String var2 = (String)var1;
int var3 = this.value.length;
if (var3 == var2.value.length) {
char[] var4 = this.value;
char[] var5 = var2.value;
for(int var6 = 0; var3-- != 0; ++var6) {
if (var4[var6] != var5[var6]) {
return false;
}
}
return true;
}
}
return false;
}
}示例:
// abc在常量池中
String a = "abc";
// 棧中b指向常量池中的abc
String b = "abc";
// 在堆內(nèi)存中重新開辟了一個(gè)abc的空間
String c = new String("abc");
//檢查字符串池里是否存在"abc"這么一個(gè)字符串,如果存在,就返回池里的字符串;如果不存在,該方法會(huì) 把"abc"添加到字符串池中,然后再返回它的引用。
String d = c.intern();
System.out.println(a==b);
System.out.println(a.equals(b));
System.out.println(a==c);
System.out.println(a.equals(c));
System.out.println(a==d);
System.out.println(a.equals(d));運(yùn)行結(jié)果:
true
true
false
true
true
trueequals的作用
引用類型:默認(rèn)情況下,比較的是地址值,重寫該方法后比較對(duì)象的成員變量值是否相同。
總結(jié)
對(duì)于復(fù)合數(shù)據(jù)類型之間進(jìn)行equals比較,在沒有覆寫equals方法的情況下,他們之間的比較還是內(nèi)存中的存放位置的地址值,跟雙等號(hào)(==)的結(jié)果相同;如果被復(fù)寫,按照復(fù)寫的實(shí)現(xiàn)來進(jìn)行比較。
分享文章:Java中equals和==的區(qū)別
鏈接分享:http://www.5511xx.com/article/ccegoes.html


咨詢
建站咨詢
