[英]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
================================================== ===============================
这里有几个我需要澄清的问题
我怀疑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
,它将等于相应的密钥。
基本上你被你可以比较int
和long
值的事实所欺骗 - 这只是编译器自动提升int
为long
; 如果你认为Integer
和Long
是完全独立的类型,它们之间没有自动转换,那么地图的行为就非常有意义了。
1.)代码正在编译,即使我将一个long作为参数传递给HashMap的get方法,该方法被声明为只有Integer作为键。 我在这里期待编译错误,因为我不知何故觉得这违反了严格的打字。
这里没有编译错误:使用泛型类型限制的参数的唯一Map方法是put
方法。 get
和containsKey
接受一个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.