簡體   English   中英

當long值傳遞給get方法時,使用整數作為鍵的映射返回null

[英]Map with integer as key returns null when long value is passed to the get method

import java.util.HashMap;
import java.util.Map;

public class StackOverFlowQuestion {

private static final int ERROR_CODE100 = -100;
private static final int ERROR_CODE101 = -101;
private static final int ERROR_CODE102 = -102;
private static final int ERROR_CODE103 = -103;
private static final int ERROR_CODE104 = -104;

public enum ErrorDetails {

    ERROR_CODE_100(ERROR_CODE100, "Error code 100 Desc", false),

    ERROR_CODE_101(ERROR_CODE101, "Error code 101 Desc", false),

    ERROR_CODE_102(ERROR_CODE102, "Error code 102 Desc", true),

    ERROR_CODE_103(ERROR_CODE103, "Error code 103 Desc", false),

    ERROR_CODE_104(ERROR_CODE104, "Error code 104 Desc", true);

    private int errorCode;
    private String errorMsg;
    private boolean canRetry;

    private ErrorDetails(int errorCode, String errorMsg, boolean canRetry) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
        this.canRetry = canRetry;
    }

    public String getErrorMsg() {
        return this.errorMsg;
    }

    public boolean canRetry() {
        return this.canRetry;
    }

    public String toString() {
        return "Error code : " + errorCode + ", errorMsg : " + errorMsg
                + ", canRetry : " + canRetry;
    }
}

private Map<Integer, ErrorDetails> errorMap;

public StackOverFlowQuestion() {
    System.out.println("StackOverFlowQuestion.StackOverFlowQuestion()");

    errorMap = new HashMap<Integer, StackOverFlowQuestion.ErrorDetails>();

    errorMap.put(ERROR_CODE100, ErrorDetails.ERROR_CODE_100);
    errorMap.put(ERROR_CODE101, ErrorDetails.ERROR_CODE_101);
    errorMap.put(ERROR_CODE102, ErrorDetails.ERROR_CODE_102);
    errorMap.put(ERROR_CODE103, ErrorDetails.ERROR_CODE_103);
    errorMap.put(ERROR_CODE104, ErrorDetails.ERROR_CODE_104);

    System.out.println("errorMap : " + errorMap);
}

/**
 * @param args
 */
public static void main(String[] args) {
    long param = -100;
    StackOverFlowQuestion question = new StackOverFlowQuestion();
    System.out.println("question.errorMap : " + question.errorMap);

    System.out.println("question.errorMap.containskey(param) : "
            + question.errorMap.containsKey(param));
    ErrorDetails errorDetails = question.errorMap.get(param);
    System.out.println("errorDetails : " + errorDetails);

    System.out.println("question.errorMap.containskey((int)param) : "
            + question.errorMap.containsKey((int) param));
    ErrorDetails errorDetailsWithInt = question.errorMap.get((int) param);
    System.out.println("errorDetailsWithInt : " + errorDetailsWithInt);

            int paramInt = -100;
    System.out.println("param == paramInt : " + (param == paramInt));
}

}

================================================== ===============================輸出:

StackOverFlowQuestion.StackOverFlowQuestion()

errorMap : {-100=Error code : -100, errorMsg : Error code 100 Desc, canRetry : false, -102=Error code : -102, errorMsg : Error code 102 Desc, canRetry : true, -101=Error code : -101, errorMsg : Error code 101 Desc, canRetry : false, -104=Error code : -104, errorMsg : Error code 104 Desc, canRetry : true, -103=Error code : -103, errorMsg : Error code 103 Desc, canRetry : false}

question.errorMap : {-100=Error code : -100, errorMsg : Error code 100 Desc, canRetry : false, -102=Error code : -102, errorMsg : Error code 102 Desc, canRetry : true, -101=Error code : -101, errorMsg : Error code 101 Desc, canRetry : false, -104=Error code : -104, errorMsg : Error code 104 Desc, canRetry : true, -103=Error code : -103, errorMsg : Error code 103 Desc, canRetry : false}

question.errorMap.containskey(param) : false
errorDetails : null

question.errorMap.containskey((int)param) : true
errorDetailsWithInt : Error code : -100, errorMsg : Error code 100 Desc, canRetry : false

param == paramInt : true

================================================== ===============================

這里有幾個我需要澄清的問題

  1. 代碼正在編譯,即使我將一個long作為參數傳遞給HashMap的get方法,該方法被聲明為只有Integer作為鍵。 我在這里期待編譯錯誤,因為我不知何故覺得這違反了嚴格的打字。
  2. 當我將包含錯誤代碼的long變量作為參數傳遞給HashMap()的get方法時,映射返回null。
  3. 當我將相同的long參數向下轉換為int並將其傳遞給哈希映射的get方法時,映射將返回正確的Enum。

我懷疑if (e.hash == hash && ((k = e.key) == key || key.equals(k))) ()方法中的if (e.hash == hash && ((k = e.key) == key || key.equals(k)))if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

我不確定int == long是否會失敗或者它們相應的包裝器是否會失敗。我甚至在main方法中添加了一個檢查以驗證int和long變量的相等性。

我想了解這里的行為。

代碼正在編譯,即使我將一個long作為參數傳遞給HashMap的get方法,該方法被聲明為只有Integer作為鍵。 我在這里期待編譯錯誤,因為我不知何故覺得這違反了嚴格的打字。

你看過Map.get的簽名了嗎?

V get(Object key)

任何對象都可以用作密鑰。 關於該設計決策還有其他Stack Overflow問題; 我稍后會找到一個。

當我將包含錯誤代碼的long變量作為參數傳遞給HashMap()的get方法時,映射返回null。

是的,它會 - 因為它將被裝箱為Long ,而Long不等於Integer 因此,在地圖中找不到該條目。

當我將相同的long參數向下轉換為int並將其傳遞給哈希映射的get方法時,映射將返回正確的Enum。

是的,它會 - 因為它將被裝箱到一個Integer ,它將等於相應的密鑰。

基本上你被你可以比較intlong值的事實所欺騙 - 這只是編譯器自動提升intlong ; 如果你認為IntegerLong是完全獨立的類型,它們之間沒有自動轉換,那么地圖的行為就非常有意義了。

1.)代碼正在編譯,即使我將一個long作為參數傳遞給HashMap的get方法,該方法被聲明為只有Integer作為鍵。 我在這里期待編譯錯誤,因為我不知何故覺得這違反了嚴格的打字。

這里沒有編譯錯誤:使用泛型類型限制的參數的唯一Map方法是put方法。 getcontainsKey接受一個Object

2.)當我將包含錯誤代碼的long變量作為參數傳遞給HashMap()的get方法時,映射返回null。

當你調用get(param)它會被轉換為get(new Long(param)) 因此參數永遠不會等於Integer

3.)當我將相同的long參數向下轉換為int並將其傳遞給哈希映射的get方法時,映射將返回正確的Enum。

當你調用get((int)param)它會被轉換為get(new Integer((int)param)) 所以參數類型現在是正確的,結果是你期望的結果。

你需要將long轉換為int。

簡短的回答是: Integer == Long總是不能相等([Long] .equal([Integer])== false)也不會Long.hashCode()== Integer.hashCode()返回相同的結果。

詳細說明答案:

由於Autoboxing,您的long將被轉換為Long,然后將其與Map中具有相同hashCode的任何其他Object進行比較。 由於HashCode的具體實現不能等於Long&Integer,因此可能已經失敗。 如果hashCodes是相同的,雖然有等待檢查要完成,這將失敗,因為像每個equals方法那樣檢查“是[Type]的實例”或返回false。 在將Long與Integer進行比較的每種情況下都會失敗。

因此,在你的情況下你需要做的就是將你長時間轉換為int或者做Integer.valueOf((int)param),這將完全相同(autoboxing)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM