Java:尝试使用错误类型作为Map键时的编译器或Eclipse警告

reo*_*toa 10 java eclipse generics

我最近被一个带有密钥类型的Map的bug所困Long,但我试图将它与类型的密钥一起使用String.我基本上有类似的东西:

Map<Long, Object> map;
...
String wrongType;
if (map.containsKey(wrongType)) {
    // Do something
} else {
    // Do something different
}
Run Code Online (Sandbox Code Playgroud)

因为映射中的所有键都是Long类型,所以代码总是执行else块.

由于containsKeyget方法采用类型的参数,因此Object可以接受任何旧类型的对象而不会抱怨.

我的困惑源于这样一个事实:在我们的系统中,同一个实体以两种不同的方式表示(有时作为a Long,有时作为a String); 我不能轻易改变这一点.有没有什么方法可以在开发时而不是在测试期间捕获这样的错误?也许是一个编译器标志或一些Eclipse选项,它更聪明一些我应该使用的方法containsKeyget方法(以及它们的类似物Set...)

rol*_*lfl 7

FindBugs对此进行了测试:GC_UNRELATED_TYPES

在你的代码上运行FindBugs应该揭示这个,还有很多其他的东西;-)


dby*_*rne 4

您可以编写一个提供类型安全性的通用实用方法:

public static <T> boolean safeContainsKey(Map<T, ?> map, T key) {
  return map.containsKey(key);
}

public static <T, U> U safeGet(Map<T, U> map, T key) {
  return map.get(key);
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您传入错误的类型,您将收到编译时错误:

//These compile fine
boolean result1 = safeContainsKey(map, 12345l);
Object obj1 = safeGet(map, 12345l);

//These cause compilation errors
boolean result2 = safeContainsKey(map, "12345");
Object obj2 = safeGet(map, "12345");
Run Code Online (Sandbox Code Playgroud)

Map您也可以实现自己的类型安全版本的接口,但这可能有点过头了。

就我个人而言,我只是运行 Google 的CodePro Analytix,它将提供有用的类型安全警告。