Java中值類型和引用類型的比較與問(wèn)題解決
一、問(wèn)題描述
前幾天因?yàn)橐粋€(gè)需求出現(xiàn)了Bug。說(shuō)高級(jí)點(diǎn)也挺高級(jí),說(shuō)白點(diǎn)也很簡(jiǎn)單。其實(shí)也就是一個(gè)很簡(jiǎn)單的Java基礎(chǔ)入門時(shí)候的值類型和引用類型的區(qū)別。只是開(kāi)發(fā)的時(shí)候由于自己的問(wèn)題,導(dǎo)致小問(wèn)題的出現(xiàn)。還好突然想起來(lái)以前看過(guò)一篇對(duì)于該問(wèn)題講解的博客,才能快速定位問(wèn)題的位置。防止下次再犯,順便也就把這個(gè)當(dāng)做筆記記錄下來(lái),放入自己的Bug集中。
二、值類型和引用類型的比較
這個(gè)大家應(yīng)該都是沒(méi)問(wèn)題的,很簡(jiǎn)單。值類型比較是比較值,引用類型是比較地址。對(duì)于正常的操作來(lái)說(shuō),比較值類型我們可以直接使用 == ,引用類型就使用equals來(lái)做比較就不會(huì)出現(xiàn)問(wèn)題。
引用類型
/** * 測(cè)試Integer */ public static void test_Integer(){ Integer number_01 = 10; Integer number_02 = 10; System.out.println(number_01.equals(number_02)); }
上面的測(cè)試結(jié)果很明顯是true,絕對(duì)沒(méi)有問(wèn)題的。
值類型
/** * 測(cè)試int */ public static void test_Int(){ int number_01 = 10; int number_02 = 10; System.out.println(number_01 == number_02); }
上面的測(cè)試結(jié)果很明顯是true,絕對(duì)沒(méi)有問(wèn)題的。
三、問(wèn)題
但是問(wèn)題就出現(xiàn)在,開(kāi)發(fā)的使用為了防止出現(xiàn)為null的時(shí)候會(huì)被系統(tǒng)使用0來(lái)代替,所以就使用了Integer類型來(lái)做操作,并且在比較的時(shí)候用了 == 。這就很尷尬了,開(kāi)始自測(cè)完全沒(méi)出現(xiàn)問(wèn)題,因?yàn)闆](méi)到達(dá)記錄數(shù)。很開(kāi)心,把代碼提交下班,妥妥的。但是尷尬的事情來(lái)了,測(cè)試報(bào)告出現(xiàn)在了郵箱里面了。
初始沒(méi)問(wèn)題的情況
/** * 測(cè)試Integer */ public static void test_Integer(){ Integer number_001 = 10; Integer number_002 = 10; System.out.println(number_001 == number_002); }
結(jié)果:
當(dāng)記錄超過(guò)一定數(shù)的時(shí)候,出現(xiàn)問(wèn)題
/** * 測(cè)試Integer */ public static void test_Integer(){ Integer number_001 = 128; Integer number_002 = 128; System.out.println(number_001 == number_002); }
結(jié)果:
四、解決
后面一想,很快確定問(wèn)題了。是自己的馬虎,偷懶使用了 == ,造成這次問(wèn)題的出現(xiàn),當(dāng)改為equals就可以妥妥的回家了。開(kāi)始自測(cè)沒(méi)問(wèn)題主要還是因?yàn)镮nteger 的緩存搞的事情。扒拉到Integer的源碼,發(fā)現(xiàn)里面用了緩存機(jī)制,對(duì)-128~127的值做了緩存,如果在這個(gè)值區(qū)間內(nèi)使用==來(lái)做比較的話,比較的就是值了,所以才造成開(kāi)始以為沒(méi)問(wèn)題,后面運(yùn)行了一段時(shí)間后就出現(xiàn)問(wèn)題了。當(dāng)不在值區(qū)間內(nèi)就必須使用equals來(lái)完成比較。
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; } private IntegerCache() {} }
五、總結(jié)
當(dāng)初面試的時(shí)候這種東西應(yīng)該是背的滾瓜爛熟,絕對(duì)可以應(yīng)對(duì)面試。但是一旦開(kāi)發(fā)起來(lái)就是各種問(wèn)題都出現(xiàn)了,而且這種東西還不會(huì)報(bào)出錯(cuò)日志,純屬開(kāi)發(fā)問(wèn)題。歸總來(lái)說(shuō)還是自己的水平不夠,還需要繼續(xù)提高。下次要防止這種低級(jí)問(wèn)題的出現(xiàn),很尷尬。同樣也是對(duì)自己學(xué)的東西要融匯貫通,而不是每學(xué)一個(gè)單獨(dú)的知識(shí)點(diǎn)就夠了,沒(méi)有起到聯(lián)通的效果。源碼扒拉一下還是會(huì)加深自己的印象。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Java實(shí)現(xiàn)統(tǒng)計(jì)文件夾下所有文件的字?jǐn)?shù)
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)統(tǒng)計(jì)文件夾下所有文件的字?jǐn)?shù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03Spring源碼如何修改Bean的屬性用到的相關(guān)類
這篇文章主要介紹了Spring源碼如何修改Bean的屬性用到的相關(guān)類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05Springboot利用Redis實(shí)現(xiàn)接口冪等性攔截
這篇文章主要為大家介紹了Springboot如何利用Redis實(shí)現(xiàn)接口冪等性攔截。本文將通過(guò)自定義注解+redis+攔截器+MD5?實(shí)現(xiàn),感興趣的可以了解一下2022-06-06Java中字符串和byte數(shù)組之間的簡(jiǎn)單轉(zhuǎn)換方法
這篇文章主要給大家介紹了關(guān)于Java中字符串和byte數(shù)組之間的簡(jiǎn)單轉(zhuǎn)換方法,Java中將String類型轉(zhuǎn)換為byte[]類型,可以使用String的getBytes()方法,還有很多其他的辦法,需要的朋友可以參考下2023-08-08Mybatis-Plus使用updateById()、update()將字段更新為null
本文主要介紹了Mybatis-Plus使用updateById()、update()將字段更新為null,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了Java實(shí)現(xiàn)基于JDBC操作mysql數(shù)據(jù)庫(kù)的方法,結(jié)合實(shí)例形式分析了java使用JDBC實(shí)現(xiàn)針對(duì)mysql數(shù)據(jù)庫(kù)的連接、查詢、輸出等相關(guān)操作技巧,需要的朋友可以參考下2017-12-12Maven編譯錯(cuò)誤:程序包c(diǎn)om.sun.*包不存在的三種解決方案
J2SE中的類大致可以劃分為以下的各個(gè)包:java.*,javax.*,org.*,sun.*,本文文章主要介紹了maven編譯錯(cuò)誤:程序包c(diǎn)om.sun.xml.internal.ws.spi不存在的解決方案,感興趣的可以了解一下2024-02-02