国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java中Objects.equals踩坑實例代碼分析

Java中Objects.equals踩坑實例代碼分析

2023-05-08 01:07未知服務器之家 Java教程

今天小編給大家分享一下Java中Objects.equals踩坑實例代碼分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來

今天小編給大家分享一下Java中Objects.equals踩坑實例代碼分析的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    1. 案發現場

    假設現在有這樣一個需求:判斷當前登錄的用戶,如果是我們指定的系統管理員,則發送一封郵件。系統管理員沒有特殊的字段標識,他的用戶id=888,在開發、測試、生產環境中該值都是一樣的。

    這個需求真的太容易實現了:

    UserInfo?userInfo?=?CurrentUser.getUserInfo();
    
    if(Objects.isNull(userInfo))?{
    ???log.info("請先登錄");
    ???return;
    }
    
    if(Objects.equals(userInfo.getId(),888))?{
    ???sendEmail(userInfo):
    }

    從當前登錄用戶的上下文中獲取用戶信息,判斷一下,如果用戶信息為空,則直接返回。

    如果獲取到的用戶信息不為空,接下來判斷用戶id是否等于888。

    • 如果等于888,則發送郵件。

    • 如果不等于888,則啥事也不干。

    當我們用id=888的系統管理員賬號登錄之后,做了相關操作,滿懷期待的準備收郵件的時候,卻發現收了個寂寞。

    后來,發現UserInfo類是這樣定義的:

    @Data
    public?class?UserInfo?{
    ????private?Long?id;
    ????private?String?name;
    ????private?Integer?age;
    ????private?String?address;
    }

    此時,有些小伙伴可能會說:沒看出什么問題呀。

    但我要說的是這個代碼確實有問題。

    什么問題呢?

    答:UserInfo類的成員變量id=888是Long類型的,而Objects.equals方法右邊的888是int類型的,兩者不一致,導致返回的結果是false。

    這算哪門子原因?

    答:各位看官,別急,后面會細講的。

    2. 判斷相等的方法

    讓我們一起回顧一下,以前判斷兩個值是否相等的方法有哪些。

    2.1 使用==號

    之前判斷兩個值是否相等,最快的方法是使用==號。

    int?a?=?1;
    int?b?=?1;
    byte?c?=?1;
    Integer?d1?=?new?Integer(1);
    Integer?d2?=?new?Integer(1);
    System.out.println(a?==?b);?
    //結果:true
    System.out.println(a?==?c);?
    //結果:true
    System.out.println(a?==?d1);?
    //結果:true
    System.out.println(d2?==?a);?
    //結果:true
    System.out.println(d1?==?d2);?
    //結果:false

    不知道大家有沒有發現,java中的基本類型,包含:int、long、short、byte、char、boolean、float、double這8種,可以使用號判斷值是否相等。如果出現了基本類型的包裝類,比如:Integer,用一個基本類型和一個包裝類,使用號也能正確判斷,返回true。

    Integer和int比較時,會自動拆箱,這是比較值是否相等。

    但如果有兩個包裝類,比如:d1和d2,使用==號判斷的結果可能是false。

    兩個Integer比較時,比較的是它們指向的引用(即內存地址)是否相等。

    還有一個有意思的現象:

    Integer?d3?=?1;
    Integer?d4?=?1;
    Integer?d5?=?128;
    Integer?d6?=?128;
    System.out.println(d3?==?d4);?
    //結果:true
    System.out.println(d5?==?d6);?
    //結果:false

    都是給Integer類型的參數,直接賦值后進行比較。d3和d4判斷的結果相等,但d5和d6判斷的結果卻不相等。

    小伙伴們,下巴驚掉了沒?

    答:因為Integer有一個常量池,-128~127直接的Integer數據直接緩存進入常量池。所以1在常量池,而128不在。

    然而,new的Integer對象不適用常量池。從之前d1和d2例子的比較結果,就能看出這一點。

    接下來,看看字符串的判斷:

    String?e?=?"abc";
    String?f?=?"abc";
    String?g?=?new?String("abc");
    String?h?=?new?String("abc");
    System.out.println(e?==?f);?
    //結果:true
    System.out.println(e?==?g);?
    //結果:false
    System.out.println(g?==?h);?
    //結果:false

    普通的字符串變量,使用==號判斷,也能返回正確的結果。

    但如果一個普通的字符串變量,跟new出來的字符串對象使用號判斷時,返回false。這一點,跟之前說過的用一個基本類型和一個包裝類,使用號判斷的結果有區別,字符串沒有自動拆箱的功能,這一點需要特別注意。

    此外,兩個new出來的字符串對象使用==號判斷時,也返回false。

    2.2 使用equals方法

    使用上面的==號,可以非常快速判斷8種基本數據類型是否相等,除此之外,還能判斷兩個對象的引用是否相等。

    但現在有個問題,它無法判斷兩個對象在內存中具體的數據值是否相等,比如:

    String?g?=?new?String("abc");
    String?h?=?new?String("abc");
    System.out.println(g?==?h);?
    //結果:false

    字符串對象g和h是兩個不同的對象,它們使用==號判斷引用是否相等時,返回的是false。

    那么,這種對象不同,但數據值相同的情況,我們該如何判斷相等呢?

    答:使用equals方法。

    equals方法其實是Object類中的方法:

    public?boolean?equals(Object?obj)?{
    ????return?(this?==?obj);
    }

    該方法非常簡單,只判斷兩個對象的引用是否相等。

    很顯然,如果字符串類型直接使用父類(即Object類)的equals方法,去判斷對象不同,但值相同的情況,是有問題的。

    所以,字符串(即String類)會重新的equals方法:

    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;
    }

    它依然會先判斷兩個對象引用是否相等,如果相等返回true。接下來,會把兩個字符串的挨個字符進行比較,只有所有字符都相等才返回true。

    nice,這樣就能解決g和h判斷的問題:

    String?e?=?"abc";
    String?f?=?"abc";
    System.out.println(e.equals(f));?
    //結果:true

    由此可見,我們使用String類重寫后的equals方法,判斷兩個字符串對象不同,但值相同時,會返回true。

    3. 空指針異常

    從前面我們已經知道,判斷兩個對象是否相等,可以使用==號,或者equals方法。

    但如果你更深入的使用它們,會發現一個問題,即:這兩種方式判斷值相等,都可能會報空指針異常。

    先看看==號判斷的情況:

    int?a?=?1;
    Integer?b?=?new?Integer(1);
    Integer?c?=?null;
    System.out.println(a?==?b);?
    //結果:true
    System.out.println(a?==?c);?
    //結果:NullPointerException

    int和Integer使用==號判斷是否相等時,Integer會自動拆箱成int。

    但由于c在自動拆箱的過程中,需要給它賦值int的默認值0。而給空對象,賦值0,必然會報空指針異常。

    接下來,看看equals方法:

    String?e?=?null;
    String?f?=?"abc";
    System.out.println(e.equals(f));?
    //結果:NullPointerException

    由于字符串對象e是空對象,直接調用它的equals方法時,就會報空指針異常。

    那么,如何解決空指針問題呢?

    答:在代碼中判空。

    String?e?=?null;
    String?f?=?"abc";
    System.out.println(equals(e,?f));

    我們抽取了一個新的equals方法:

    private?static?boolean?equals(String?e,?String?f)?{
    ????if?(e?==?null)?{
    ????????return?f?==?null;
    ????}
    ????return?e.equals(f);
    }

    該方法可以解決空指針問題,但有沒有辦法封裝一下,變得更通用一下,也適用于Integer或者其他類型的對象比較呢?

    答:有辦法,繼續往下看。

    4. Objects.equals的作用

    Objects類位于java.util包下,它是里面提供了很多對象操作的輔助方法。

    下面我們重點看看它的equals方法:

    public?static?boolean?equals(Object?a,?Object?b)?{
    ????return?(a?==?b)?||?(a?!=?null?&&?a.equals(b));
    }

    equals方法的判斷邏輯如下:

    • 該方法先判斷對象a和b的引用是否相等,如果相等則直接返回true。

    • 如果引用不相等,則判斷a是否為空,如果a為空則返回false。

    • 如果a不為空,調用對象的equals方法進一步判斷值是否相等。

    該方法是如何使用的?

    int?a?=?1;
    int?b?=?1;
    Integer?c?=?null;
    
    System.out.println(Objects.equals(a,?c));?
    //結果:false
    System.out.println(Objects.equals(c,?a));?
    //結果:false
    System.out.println(Objects.equals(a,?b));?
    //結果:true

    從上面的列子看出,使用Objects.equals方法比較兩個對象是否相等,確實可以避免空指針問題。

    但這個有個疑問:前面使用a==b這種方式比較引用是否相等,當時b為空時,程序直接拋了空指針異常。

    而Objects.equals方法內部也使用了a==b比較引用是否相等,為啥它沒有拋異常?

    答:因為而Objects類的equals方法,使用了Object類型接收參數,它的默認值是null,不用進行類型轉換,也不用像int類型對象賦值默認值0。

    從上面的理論可以看出,如果我們把代碼改成這樣,也不會拋異常:

    int?a?=?1;
    Integer?c?=?null;
    System.out.println(equals(a,?c));
    //結果:false

    新定義了一個方法:

    private?static?boolean?equals(Object?a,?Object?b)?{
    ????return?a?==?b;
    }

    執行之后發現,確實沒有拋空指針了。

    所以Objects.equals方法再比較兩個對象是否相等時,確實是一個不錯的方法。

    但它有坑,不信繼續往下看。

    5. Objects.equals的坑

    各位小伙們看到這里,可能有點心急了,到底是什么坑?

    廢話不多說,直接上例子:

    Integer?a?=?1;
    long?b?=?1L;
    System.out.println(Objects.equals(a,?b));
    //結果:false

    什么?返回結果是false?

    而如果你直接用==號判斷:

    Integer?a?=?1;
    long?b?=?1L;
    System.out.println(a?==?b);
    //結果:true

    返回又是true。

    a和b明明都是1,為什么使用Objects.equals方法判斷不相等呢?

    這就要從Integer的equals方法說起來了。

    它的equals方法具體代碼如下:

    public?boolean?equals(Object?obj)?{
    ????if?(obj?instanceof?Integer)?{
    ????????return?value?==?((Integer)obj).intValue();
    ????}
    ????return?false;
    }

    先判斷參數obj是否是Integer類型,如果不是,則直接返回false。如果是Integer類型,再進一步判斷int值是否相等。

    而上面這個例子中b是long類型,所以Integer的equals方法直接返回了false。

    也就是說,如果調用了Integer的equals方法,必須要求入參也是Integer類型,否則該方法會直接返回false。

    原來坑在這里!!!

    其實,如果把代碼改成這樣:

    Integer?a?=?1;
    long?b?=?1L;
    System.out.println(Objects.equals(b,?a));
    //結果:false

    執行結果也是false。

    因為Long的equals方法代碼,跟之前Integer的類似:

    public?boolean?equals(Object?obj)?{
    ????if?(obj?instanceof?Long)?{
    ????????return?value?==?((Long)obj).longValue();
    ????}
    ????return?false;
    }

    也是判斷入參,如果不是Long類型,則該方法直接返回false。

    除此之外,還有Byte、Short、Double、Float、Boolean和Character也有類似的equals方法判斷邏輯。

    由此可見,我們在使用Objects.equals方法,判斷兩個值是否相等時,一定要保證兩個入參的類型要一致。否則即使兩個值相同,但其結果仍然會返回false,這是一個大坑。

    那么,如何解決上面的問題呢?

    可以將參數b的類型強制轉換成int。

    Integer?a?=?1;
    long?b?=?1L;
    System.out.println(Objects.equals(a,?(int)b));
    //結果:true

    或者將參數a的類型強制轉換成long。

    Integer?a?=?1;
    long?b?=?1L;
    System.out.println(Objects.equals(b,?(long)a));
    //結果:true

    有些情況也可以直接用==號判斷:

    Integer?a?=?1;
    long?b?=?1L;
    System.out.println(a==b);
    //結果:true

    除了Objects.equals方法在兩個入參類型不同,而會直接返回false之外,java的8種基本類型包裝類的equals也會有相同的問題,需要小伙們特別注意。

    之前,如果直接使用java基本類型包裝類的equals方法判斷相等。

    Integer?a?=?new?Integer(1);
    long?b?=?1L;
    System.out.println(a.equals(b));

    在idea中,如果你將鼠標放在equals方法上,會出現下面的提示:

    Java中Objects.equals踩坑實例代碼分析

  • Long類型和Integer類型比較,比如:用戶id的場景。

  • Byte類型和Integer類型比較,比如:狀態判斷的場景。

  • Double類型和Integer類型比較,比如:金額為0的判斷場景。

  • 以上就是“Java中Objects.equals踩坑實例代碼分析”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注***行業資訊頻道。

    延伸 · 閱讀

    精彩推薦
    主站蜘蛛池模板: 亚洲视频在线观看视频 | 精品国产三级 | 国产精品乱码久久 | 黄色一级片一级片 | 欧美一级欧美三级在线观看 | 成人午夜在线 | 国内精品一级毛片 | 中文字幕123 | 亚洲永久免费 | 在线一区二区三区四区 | 在线天堂av | 欧美一级片在线 | 国产一区二区三区在线免费看 | 先锋资源在线观看 | 93看片淫黄大片一级 | 精品国产色 | 久久99精品国产自在现线 | 成人av电影天堂 | 国产精品亚洲第一 | 色综合色综合网色综合 | 国产精品久久久久久99999 | 久久精品国产免费 | 成人在线欧美 | 91香蕉视频在线 | 亚洲尤物在线 | 狠狠操操 | 最新电影在线高清免费完整观看视频 | 亚洲成人aaaa | 国产黄色在线观看 | 欧美日韩91 | 精品久久国产 | 欧美日韩视频 | 国产精品福利在线 | 精品第一页 | 日本一区二区三区四区 | 成人免费淫片aa视频免费 | 国产精品日韩高清伦字幕搜索 | 国产欧美综合一区二区三区 | 国产xnxx| 亚洲va欧美va人人爽成人影院 | 免费看黄在线网站 |