對于基本數(shù)據(jù)類型:(byte、short休涤、char咱圆、int笛辟、float功氨、double、long手幢、boolean)捷凄,比較的是值。
他們是作為常量在方法區(qū)中的常量池里面以HashSet策略存儲起來的围来,對于這樣的字符串 "123" 也是相同的道理跺涤,在常量池中,一個常量只會對應(yīng)一個地址监透,因此不管是再多的 123桶错,"123" 這樣的數(shù)據(jù)都只會存儲一個地址,所以所有他們的引用都是指向的同一塊地址胀蛮,因此基本數(shù)據(jù)類型和String常量是可以直接通過==來直接比較的院刁。
對于引用數(shù)據(jù)類型,有equals和==兩種比較方法粪狼。
什么是==?
== 等于比較運算符退腥,如果進(jìn)行比較的兩個操作數(shù)都是數(shù)值類型,即使他們的數(shù)據(jù)類型不相同再榄,只要他們的值相等狡刘,也都將返回true。如果兩個操作數(shù)都是引用類型困鸥,那么只有當(dāng)兩個引用變量的類型具有父子關(guān)系時才可以比較嗅蔬,而且這兩個引用必須指向同一個對象,才會返回true(在這里我們可以理解成==比較的是兩個變量的內(nèi)存地址)。
什么是equals()?
equals()方法是Object類的方法购城,在Object類中的equals()方法體內(nèi)實際上返回的就是使用==進(jìn)行比較的吕座。但是我們知道所有的類都繼承Object,而且Object中的equals()方法沒有使用final關(guān)鍵字修飾瘪板,那么當(dāng)我們使用equal()方法進(jìn)行比較的時候吴趴,我們需要關(guān)注的就是這個類有沒有重寫Object中的equals()方法。
如果自己所寫的類中已經(jīng)重寫了equals方法侮攀,那么就按照用戶自定義的方式來比較倆個對象是否相等锣枝,如果沒有重寫過equal方法,那么會調(diào)用父類(Object)中的equals方法進(jìn)行比較兰英,也就是比較地址值撇叁。
JVM把內(nèi)存劃分成兩種:一種是棧內(nèi)存,一種是堆內(nèi)存畦贸。
≡赡帧①在函數(shù)中定義的一些基本類型的變量和對象的引用變量(變量名)都在函數(shù)的棧內(nèi)存中分配。
”』怠②當(dāng)在一段代碼塊定義一個變量時趋厉,Java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后胶坠,Java會自動釋放掉為該變量所分配的內(nèi)存空間君账,該內(nèi)存空間可以立即被另作他用。
∩蛏啤③堆內(nèi)存用來存放由new創(chuàng)建的對象(包括由基本類型包裝起來的類:Integer乡数、String、Double闻牡,實際上每個基本類型都有他的包裝類)和數(shù)組净赴。
Object類中的equals方法:
public boolean equals(Object obj) {
return (this == obj);
}
可以看出Object類中equals方法是用==判斷對象引用是否指向同一內(nèi)存地址。
String源碼講解
舉例
Stringst1="hello";
Stringst2="hello";
System.out.println(st1==st2);//true
st1.equals(st2);//true
講解:String類型罩润,它已經(jīng)實現(xiàn)了重寫玖翅,比較的時候,先比較當(dāng)前對象的地址和要比較的對象的地址是否相等哨啃,若相等烧栋,則返回true,則拳球,提前結(jié)束比較审姓。
如果不相等,則判斷是否為String的實例化對象祝峻,如果是魔吐,在判斷長度是否相等扎筒,再判斷數(shù)組的每個值,字母是否相等酬姆。如果都相等嗜桌,則返回true。
上面的判斷當(dāng)執(zhí)行String s1 = “hello”辞色;這條語句時骨宠,會在堆中的字符常量池里找”hello”這個字符串,若沒有找到相满,則將”hello”這個字符串放入字符串常量池中层亿。而在棧中開辟一塊名為s1的空間存放”hello”,這塊空間的引用立美。當(dāng)執(zhí)行String s2 = “hello”匿又;這條語句時,會在堆中的字符串常量池里找”hello”這個字符串建蹄,很顯然可以找到碌更,于是便把字符常量里”hello”這個字符串的引用地址賦給s2,因此s1與s2存放的都是堆中字符常量池中的同一個”hello”的引用洞慎。
Stringst2="hello";
Stringst3=newString("hello");
System.out.println(st2==st3);//false 因為重現(xiàn)new出來的痛单,就會重新開辟一塊地址,所以比較的的是引用的地址值拢蛋, false
st1.equals(st2);//true 因為String已經(jīng)重寫了equals方法桦他,比較的是值蔫巩,則相等
Stringsss1=newString("aaa");
Stringsss2=newString("aaa");
System.out.println(sss1==sss2);//false
System.out.println(sss1.equals(sss2));// true
sss1和sss2都為new出來的對象谆棱,各占有一塊內(nèi)存空間,所以內(nèi)存地址不同圆仔,但是字符串內(nèi)容相同垃瞧。
StringBufferstringBuffer=newStringBuffer("aaa");
StringBufferstringBuffer2=newStringBuffer("aaa");
System.out.println(stringBuffer==stringBuffer2);// false
System.out.println(stringBuffer.equals(stringBuffer2));// false
非String類,例如StringBuffer類 沒有重寫equals方法坪郭,所以不比較內(nèi)容个从。==和equals都是比較的內(nèi)存地址。
區(qū)別
== 是java提供的等于比較運算符歪沃,用來比較兩個變量指向的內(nèi)存地址是否相同嗦锐。而equals()是Object提供的一個方法。Object中equals()方法的默認(rèn)實現(xiàn)就是返回兩個對象==的比較結(jié)果沪曙。但是equals()可以被重寫奕污,所以我們在具體使用的時候需要關(guān)注equals()方法有沒有被重。
通俗一點液走,我們需要記住的就是==比較的是內(nèi)存地址碳默,是java提供的比較運算符贾陷,而equals()方法是Object中提供的方法,是可以被重寫的嘱根,你也可以自己重寫髓废,所以在使用equals()方法時應(yīng)該看看此類是如何重寫的,僅此而已该抒。
從==和equals可以引申出equals和hashcode方法的重寫慌洪。