Java 如何处理未检查的强制转换警告?
Eclipse向我发出以下形式的警告: 类型安全性:未选中从对象到HashMap的强制转换 这是对API的调用,我无法控制该API返回的对象:Java 如何处理未检查的强制转换警告?,java,generics,warnings,Java,Generics,Warnings,Eclipse向我发出以下形式的警告: 类型安全性:未选中从对象到HashMap的强制转换 这是对API的调用,我无法控制该API返回的对象: HashMap<String, String> getItems(javax.servlet.http.HttpSession session) { HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("at
HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey");
return theHash;
}
当您尝试使用哈希时,问题出现在其他地方,您会收到警告:
HashMap getItems(javax.servlet.http.HttpSession session) {
HashMap theHash = (HashMap)session.getAttribute("attributeKey");
return theHash;
}
HashMap items = getItems(session);
items.put("this", "that");
Type safety: The method put(Object, Object) belongs to the raw type HashMap. References to generic type HashMap<K,V> should be parameterized.
HashMap items=getItems(会话);
项目。放入(“该”、“该”);
类型安全:方法put(Object,Object)属于原始类型HashMap。对泛型类型HashMap的引用应该参数化。
如果你发布你的代码,快速猜测可以肯定,但你可能已经按照
HashMap<String, Object> test = new HashMap();
HashMap test=newhashmap();
当你需要做的时候会产生警告
HashMap<String, Object> test = new HashMap<String, Object>();
HashMap test=newhashmap();
这可能值得一看
如果您不熟悉需要做什么。我可能误解了这个问题(一个示例和几行环绕的行就好了),但是为什么您不总是使用适当的接口(和Java5+)?我看不出你有什么理由想要转换成
HashMap
而不是Map
。事实上,我无法想象有什么理由将变量的类型设置为HashMap
,而不是Map
为什么源是
对象
?它是旧集合的参数类型吗?如果是这样,请使用泛型并指定所需的类型。显然,答案不是执行未选中的强制转换
如果绝对必要,那么至少尝试限制@SuppressWarnings
注释的范围。根据its,它可以处理局部变量;这样,它甚至不会影响整个方法
例如:
@SuppressWarnings("unchecked")
Map<String, String> myMap = (Map<String, String>) deserializeMap();
@SuppressWarnings(“未选中”)
Map myMap=(Map)反序列化映射();
无法确定
映射
是否真的应该具有通用参数
。您必须事先知道参数应该是什么(或者当您得到ClassCastException
时就会知道)。这就是代码生成警告的原因,因为编译器不可能知道是否安全。在强制转换之前只需键入检查即可
Object someObject = session.getAttribute("attributeKey");
if(someObject instanceof HashMap)
HashMap<String, String> theHash = (HashMap<String, String>)someObject;
objectsomeobject=session.getAttribute(“attributeKey”);
if(HashMap的someObject实例)
HashMap theHash=(HashMap)someObject;
对于任何询问的人来说,在不确定对象类型的情况下接收对象是很常见的。许多遗留的“SOA”实现传递各种您不应该总是信任的对象。(恐怖!)
EDIT将示例代码更改了一次,以匹配海报的更新,在一些评论之后,我发现instanceof不能很好地处理泛型。但是,更改检查以验证外部对象似乎与命令行编译器配合得很好。修订后的示例现已发布。Wow;我想我找到了我自己问题的答案。我只是不确定这是否值得!:) 问题是演员阵容没有被检查。所以,你必须亲自检查。不能仅使用instanceof检查参数化类型,因为参数化类型信息在运行时不可用,在编译时已被删除 但是,您可以使用instanceof对散列中的每一项执行检查,这样,您就可以构造一个类型安全的新散列。你不会引起任何警告 多亏了mmyers和Esko Luontola,我已经参数化了我最初在这里编写的代码,所以它可以封装在某个地方的实用程序类中,并用于任何参数化HashMap。如果您想更好地理解它,并且不太熟悉泛型,我建议您查看此答案的编辑历史记录
public static <K, V> HashMap<K, V> castHash(HashMap input,
Class<K> keyClass,
Class<V> valueClass) {
HashMap<K, V> output = new HashMap<K, V>();
if (input == null)
return output;
for (Object key: input.keySet().toArray()) {
if ((key == null) || (keyClass.isAssignableFrom(key.getClass()))) {
Object value = input.get(key);
if ((value == null) || (valueClass.isAssignableFrom(value.getClass()))) {
K k = keyClass.cast(key);
V v = valueClass.cast(value);
output.put(k, v);
} else {
throw new AssertionError(
"Cannot cast to HashMap<"+ keyClass.getSimpleName()
+", "+ valueClass.getSimpleName() +">"
+", value "+ value +" is not a "+ valueClass.getSimpleName()
);
}
} else {
throw new AssertionError(
"Cannot cast to HashMap<"+ keyClass.getSimpleName()
+", "+ valueClass.getSimpleName() +">"
+", key "+ key +" is not a " + keyClass.getSimpleName()
);
}
}
return output;
}
公共静态HashMap castHash(HashMap输入,
类键类,
类值(类){
HashMap输出=新的HashMap();
如果(输入==null)
返回输出;
for(对象键:input.keySet().toArray()){
if((key==null)| |(keyClass.isAssignableFrom(key.getClass())){
对象值=输入。获取(键);
if((value==null)| |(valueClass.isAssignableFrom(value.getClass())){
K=keyClass.cast(键);
V=价值等级.cast(价值);
输出电压(k,v);
}否则{
抛出新断言错误(
“无法强制转换为HashMap”
+,值“+value+”不是“+valueClass.getSimpleName()
);
}
}否则{
抛出新断言错误(
“无法强制转换为HashMap”
+,键“+key+”不是“+keyClass.getSimpleName()
);
}
}
返回输出;
}
这是一个很大的工作,可能只有很少的报酬。。。我不确定我是否会用它。我很感激任何关于人们是否认为值得的评论。此外,我也希望得到改进建议:除了抛出断言错误,我还能做些更好的事情吗?有更好的吗?我应该将其设置为选中的异常吗?不幸的是,这里没有很好的选项。请记住,所有这些的目标都是保护类型安全。“”提供了一种处理非泛型遗留库的解决方案,在第8.2节中有一种特别称为“空循环技术”。基本上,进行不安全强制转换,并抑制警告。然后像这样在地图上循环:
@SuppressWarnings("unchecked")
Map<String, Number> map = getMap();
for (String s : map.keySet());
for (Number n : map.values());
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
Object obj = map;
Map<String, Integer> ok = safeCastMap(obj, String.class, Integer.class);
Map<String, String> error = safeCastMap(obj, String.class, String.class);
}
@SuppressWarnings({"unchecked"})
public static <K, V> Map<K, V> safeCastMap(Object map, Class<K> keyType, Class<V> valueType) {
checkMap(map);
checkMapContents(keyType, valueType, (Map<?, ?>) map);
return (Map<K, V>) map;
}
private static void checkMap(Object map) {
checkType(Map.class, map);
}
private static <K, V> void checkMapContents(Class<K> keyType, Class<V> valueType, Map<?, ?> map) {
for (Map.Entry<?, ?> entry : map.entrySet()) {
checkType(keyType, entry.getKey());
checkType(valueType, entry.getValue());
}
}
private static <K> void checkType(Class<K> expectedType, Object obj) {
if (!expectedType.isInstance(obj)) {
throw new IllegalArgumentException("Expected " + expectedType + " but was " + obj.getClass() + ": " + obj);
}
}
@SuppressWarnings("unchecked")
Vector<String> watchedSymbolsClone = (Vector<String>) watchedSymbols.clone();
this.watchedSymbols = watchedSymbolsClone;
@SuppressWarnings(“未选中”)
Map Map=getMap();
for(字符串s:map.keySet());
for(编号n:map.values());
如果遇到意外的类型,您将得到运行时
ClassCastException
,但至少它会发生在问题的根源附近。如果我必须使用不支持泛型的API。。我尝试用尽可能少的行在包装器例程中隔离这些调用。然后,我使用SuppressWarnings注释并添加ty
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
Object obj = map;
Map<String, Integer> ok = safeCastMap(obj, String.class, Integer.class);
Map<String, String> error = safeCastMap(obj, String.class, String.class);
}
@SuppressWarnings({"unchecked"})
public static <K, V> Map<K, V> safeCastMap(Object map, Class<K> keyType, Class<V> valueType) {
checkMap(map);
checkMapContents(keyType, valueType, (Map<?, ?>) map);
return (Map<K, V>) map;
}
private static void checkMap(Object map) {
checkType(Map.class, map);
}
private static <K, V> void checkMapContents(Class<K> keyType, Class<V> valueType, Map<?, ?> map) {
for (Map.Entry<?, ?> entry : map.entrySet()) {
checkType(keyType, entry.getKey());
checkType(valueType, entry.getValue());
}
}
private static <K> void checkType(Class<K> expectedType, Object obj) {
if (!expectedType.isInstance(obj)) {
throw new IllegalArgumentException("Expected " + expectedType + " but was " + obj.getClass() + ": " + obj);
}
}
public final class Items implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Map<String,String> map;
public Items(Map<String,String> map) {
this.map = New.immutableMap(map);
}
public Map<String,String> getMap() {
return map;
}
@Override public String toString() {
return map.toString();
}
}
public final class New {
public static <K,V> Map<K,V> immutableMap(
Map<? extends K, ? extends V> original
) {
// ... optimise as you wish...
return Collections.unmodifiableMap(
new HashMap<String,String>(original)
);
}
}
static Map<String, String> getItems(HttpSession session) {
Items items = (Items)
session.getAttribute("attributeKey");
return items.getMap();
}
import java.util.AbstractMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Attributes extends AbstractMap<String, String> {
final Map<String, String> content = new HashMap<String, String>();
@Override
public Set<Map.Entry<String, String>> entrySet() {
return content.entrySet();
}
@Override
public Set<String> keySet() {
return content.keySet();
}
@Override
public Collection<String> values() {
return content.values();
}
@Override
public String put(final String key, final String value) {
return content.put(key, value);
}
}
HashMap<?,?> getItems(javax.servlet.http.HttpSession session) {
HashMap<?,?> theHash = (HashMap<?,?>)session.getAttribute("attributeKey");
return theHash;
}
static Map<String, String> getItems(HttpSession session) {
HashMap<?, ?> theHash1 = (HashMap<String,String>)session.getAttribute("attributeKey");
HashMap<String,String> theHash = (HashMap<String,String>)theHash1;
return theHash;
}
@SuppressWarnings("unchecked")
public static <K, V> HashMap<K, V> toHashMap(Object input, Class<K> key, Class<V> value) {
assert input instanceof Map : input;
for (Map.Entry<?, ?> e : ((HashMap<?, ?>) input).entrySet()) {
assert key.isAssignableFrom(e.getKey().getClass()) : "Map contains invalid keys";
assert value.isAssignableFrom(e.getValue().getClass()) : "Map contains invalid values";
}
if (input instanceof HashMap)
return (HashMap<K, V>) input;
return new HashMap<K, V>((Map<K, V>) input);
}
package scratchpad;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
public class YellowMouse {
// First way
Map<String, String> getHashMapStudiouslyAvoidingSuppressTag(HttpSession session) {
Map<?, ?> theHash = (Map<?, ?>)session.getAttribute("attributeKey");
Map<String, String> yellowMouse = new HashMap<String, String>();
for( Map.Entry<?, ?> entry : theHash.entrySet() ){
yellowMouse.put( (String)entry.getKey(), (String)entry.getValue() );
}
return yellowMouse;
}
// Second way
Map<String, String> getHashMapUsingNaughtyButNiceUtilityMethod(HttpSession session) {
return uncheckedCast( session.getAttribute("attributeKey") );
}
// NB this is a utility method which should be kept in your utility library. If you do that it will
// be the *only* time in your entire life that you will have to use this particular tag!!
@SuppressWarnings({ "unchecked" })
public static synchronized <T> T uncheckedCast(Object obj) {
return (T) obj;
}
}
@SuppressWarnings("unchecked")
Vector<String> watchedSymbolsClone = (Vector<String>) watchedSymbols.clone();
this.watchedSymbols = watchedSymbolsClone;
this.watchedSymbols = Objects.uncheckedCast(watchedSymbols.clone());
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1);
Object intListObject = intList;
// this line gives an unchecked warning - but no runtime error
ArrayList<String> stringList = (ArrayList<String>) intListObject;
System.out.println(stringList.get(0)); // cast exception will be given here
public abstract class Section<T extends Section> extends Element<Section<T>> {
Object attr1;
/**
* Compare one section object to another.
*
* @param obj the object being compared with this section object
* @return true if this section and the other section are of the same
* sub-class of section and their component fields are the same, false
* otherwise
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
// this exists, but obj doesn't, so they can't be equal!
return false;
}
// prepare to cast...
Section<?> other;
if (getClass() != obj.getClass()) {
// looks like we're comparing apples to oranges
return false;
} else {
// it must be safe to make that cast!
other = (Section<?>) obj;
}
// and then I compare attributes between this and other
return this.attr1.equals(other.attr1);
}
}
HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
// first, cast the returned Object to generic HashMap<?,?>
HashMap<?, ?> theHash = (HashMap<?, ?>)session.getAttribute("attributeKey");
// next, cast every entry of the HashMap to the required type <String, String>
HashMap<String, String> returingHash = new HashMap<>();
for (Entry<?, ?> entry : theHash.entrySet()) {
returingHash.put((String) entry.getKey(), (String) entry.getValue());
}
return returingHash;
}
public void dragFinished(StructuredViewer structuredViewer, Class<T> inputElementClazz) {
IStructuredSelection selection = (IStructuredSelection) structuredViewer.getSelection();
// legacy code returns an Object from getFirstElement,
// the developer knows/hopes it is of type inputElementClazz, but the compiler cannot know
T firstElement = inputElementClazz.cast(selection.getFirstElement());
// legacy code returns an object from getInput, so we deal with it as a Collection<?>
Collection<?> unknownTypeCollection = (Collection<?>) structuredViewer.getInput();
// for some operations we do not even need a collection with known types
unknownTypeCollection.remove(firstElement);
// nothing prevents us from building a Collection of a known type, should we really need one
Collection<T> knownTypeCollection = new ArrayList<T>();
for (Object object : unknownTypeCollection) {
T aT = inputElementClazz.cast(object);
knownTypeCollection.add(aT);
System.out.println(aT.getClass());
}
structuredViewer.refresh();
}
dragFinishedStrategy.dragFinished(viewer, Product.class);
//noinspection unchecked
Map<String, String> myMap = (Map<String, String>) deserializeMap();