聽說,你也一直鐘愛著equals。。。

来源:https://www.cnblogs.com/buguge/archive/2018/01/29/8361329.html
-Advertisement-
Play Games

因為每個枚舉常量只有一個實例,所以如果在比較兩個參考值,至少有一個涉及到枚舉常量時,允許使用“==”代替equals() ...


腦補一下final

final 用於聲明變數/參數/屬性、方法和類。

  • 修飾變數:如果變數是基本類型,其值不變;如果是對象,則引用不可再變(內容可變)。
  • 修飾方法:方法不可重寫(是否可繼承取決於方法的訪問修飾符)
  • 修飾類:類不可被繼承。

 



 

==與equals的區別

 

我想,大家常規的解釋是:==是操作符,比較基本類型,則為其值;比較引用類型,則用以比較兩個對象在記憶體中的哈希地址。 equals是方法,比較的是變數的內容。

---------------

equals是超類Object的方法。參數是一個object對象。

 


java.lang.Object里對equals方法的說明:

/**

Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null object references:
  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Parameters:
obj - the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise.
See Also:
hashCode(), java.util.HashMap
*/
public boolean equals(Object obj) {
    return (this == obj);
}

可見equals預設是比較對象的哈希值。

 

String、Integer這些包裝類重寫了equals方法。重寫的邏輯都是先判斷類型是否匹配,然後String是看字元串里每個char字元是否都相同,Integer是兩個Integer實例的intValue。

//java.lang.Integer

/**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
*/
    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;
}



//java.lang.Integer

/**
     * Compares this object to the specified object.  The result is
     * {@code true} if and only if the argument is not
     * {@code null} and is an {@code Integer} object that
     * contains the same {@code int} value as this object.
*/
public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
}
java.lang.String和java.lang.Integer對equals(Object)方法的定義

 

BTW,心細的同學可以註意一下java.lang.String中另一個方法equalsIgnoreCase,其參數類型是String。這一點可見java之美。

 

在做諸如String、Integer包裝類型比較時,有的人一律用equals,這樣會規避用==帶來的比較錯誤的問題。這沒錯!不過使用equals也會帶來一些隱性的bug,罪魁禍首就是它的參數類型是Object,當equals的兩個對象類型不匹配時,編譯器是識別不出來的。尤其當我們重構代碼時,舉個慄子,看下麵的語句,如果我將bean的platformCode屬性的類型由String改為int,而稍有不慎忘記改下麵的語句,那就出bug了。

if("6".equals(bean.getPlatformCode())

 因此,個人認為。。。(此處見解見文末)

 



 

比較枚舉類型能用==嗎?

 

今天有同學在review代碼時,發現如下用==來比較枚舉,馬上反問這麼寫沒有bug麽?是否測試過了?

if (ThirdPayPlatformEnums.TFB == _requestDTO.getThird_pay_platform()) {
_requestDTO.setOrder_no(_requestDTO.getOrder_no().replaceAll("[a-zA-Z]", ""));
}

他讓改用equals。

於是,大家都開始思考枚舉是不是基本類型,並瞭解枚舉是否可以用==來比較。

經查,答案是肯定的。

java.lang.Enum類對equals的定義是這樣的:

public final boolean equals(Object other) {
return this==other;
}

單看這個方法實現,可能認為比較的是哈希地址。

讓我們關註一下一些關鍵詞,看這個方法的註解:

/**
* Returns true if the specified object is equal to this
* enum constant.
*
* @param other the object to be compared for equality with this object.
* @return true if the specified object is equal to this
* enum constant.
*/

註意,它將枚舉項稱為枚舉常量。

進一步瞭解到:在官方文檔中也有明確的說明

 JLS 8.9 Enums 一個枚舉類型除了定義的那些枚舉常量外沒有其他實例了。 試圖明確地說明一種枚舉類型是會導致編譯期異常。在枚舉中final clone方法確保枚舉常量從不會被克隆,而且序列化機制會確保從不會因為反序列化而創造複製的實例。枚舉類型的反射實例化也是被禁止的。總之,以上內容確保了除了定義的枚舉常量之外,沒有枚舉類型實例。

 因為每個枚舉常量只有一個實例,所以如果在比較兩個參考值,至少有一個涉及到枚舉常量時,允許使用“==”代替equals()。

順便貼出來java.lang.Enum里的clone方法,它保證了枚舉的“單例”狀態:

/**
* Throws CloneNotSupportedException. This guarantees that enums are never cloned, which is necessary to preserve their "singleton" status.
*
* @return (never returns)
*/
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}

csdn《 比較java枚舉成員使用equal還是==》文中分析了分別用==和equals來比較枚舉的場景。最終建議是最好用==,也是考慮到了上文中提到的equals的弊端。 同樣,如果是數值比較,也最好用基本類型,因為用==來比較數值無爭議。

 

 



 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這幾天使用H5開發了一個仿微信聊天前端界面,尤其微信底部編輯器那塊處理的很好,使用HTML5來開發,雖說功能效果並沒有微信那麼全,但是也相當不錯了,可以發送消息、表情,發送的消息自動回滾定位到底部,另外可以對消息、圖片、視頻有不同的右鍵處理提示,還有打賞、占屏等操作。 html代碼片段: Javas ...
  • 最近想找換一份工作,於是去面試了一家比較大的公司,以下是面試官問的幾個關於技術的面試題。 一.css裡面有個position,你知道它都有那幾個值嗎,以及它們的作用是什麼? 這個我回答的是: position一共有absolute,fixed,relative,static,inherit這幾個值, ...
  • A代碼編輯器,線上模版編輯,仿開發工具編輯器,pdf線上預覽,文件轉換編碼 B 集成代碼生成器 [正反雙向](單表、主表、明細表、樹形表,快速開發利器)+快速表單構建器 freemaker模版技術 ,0個代碼不用寫,生成完整的一個模塊,帶頁面、建表sql腳本,處理類,service等完整模塊 C 集 ...
  • 前文涉及到了很多與Leader相關的演算法,大家有木有想過,王侯將相,寧有種乎,既然Leader這麼麻煩,乾脆還是採用P2P模型吧,來個大家平等的架構。本篇需要和大家探討的就是多副本下實現民主政治的 Quorum機制 。至於它是怎麼樣解決我們在前文提及的各種問題的,接著這篇文章我們繼續聊聊~~ 1. ...
  • Redis的使用難嗎?不難,Redis用好容易嗎?不容易。Redis的使用雖然不難,但與業務結合的應用場景特別多、特別緊,用好並不容易。我們希望通過一篇文章及Demo,即可輕鬆、快速入門並學會應用。 一、Redis 簡介 Redis是一個開源的Key-Value存儲,但又不僅僅是Key-Value存 ...
  • server下的方法:bind() , listen(), accept(), recv(), send(bytes(String)), sendall(), client的方法:connect(), recv(), send(), sendall()### 建立通信的過程:創建socket,綁定i ...
  • 這個消息比較實用也很關鍵,它代表非顯示區域命中測試。這個消息優先於所有其他的顯示區域和非顯示區域滑鼠消息。其中lParam參數含有滑鼠位置的x和y屏幕坐標,wParam 這裡沒有用。 Windows應用程式通常把這個消息傳送給DefWindowProc,然後Windows用WM_NCHITTEST消 ...
  • 1、connect描述:實例連接到一個Redis.參數:host: string,port: int返回值:BOOL 成功返回:TRUE;失敗返回:FALSE示例:$redis = new redis(); $result = $redis->connect('127.0.0.1', 6379); ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...