Eclipse给我一个如下形式的警告:

类型安全:未检查从对象转换到HashMap

这是从一个API调用,我无法控制返回对象:

HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
  HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey");
  return theHash;
}

如果可能的话,我希望避免使用Eclipse警告,因为理论上它们至少表明存在潜在的代码问题。不过,我还没有找到消除这个问题的好方法。我可以将所涉及的单行单独提取到一个方法中,并向该方法添加@SuppressWarnings(“unchecked”),从而限制忽略警告的代码块的影响。有更好的选择吗?我不想在Eclipse中关闭这些警告。

在我接触代码之前,它更简单,但仍然引起了警告:

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<String, Object> test = new HashMap();

当你需要做的时候,哪个会产生警告

HashMap<String, Object> test = new HashMap<String, Object>();

也许值得一看

Java编程语言中的泛型

如果你不熟悉需要做什么。

其他回答

在强制转换之前检查一下。

Object someObject = session.getAttribute("attributeKey");
if(someObject instanceof HashMap)
HashMap<String, String> theHash = (HashMap<String, String>)someObject;  

对于任何提问的人来说,收到你不确定类型的对象是很常见的。大量遗留的“SOA”实现传递各种对象,您不应该总是信任这些对象。(恐怖!)

EDIT修改了示例代码一次,以匹配海报的更新,在一些评论之后,我看到instanceof不能很好地使用泛型。然而,更改检查以验证外部对象似乎可以很好地使用命令行编译器。修订的例子现在发布。

如果你确定session.getAttribute()返回的类型是HashMap,那么你不能精确地将其类型转换为该类型,而只能依赖于检查泛型HashMap

HashMap<?,?> getItems(javax.servlet.http.HttpSession session) {  
    HashMap<?,?> theHash = (HashMap<?,?>)session.getAttribute("attributeKey");
    return theHash;
} 

Eclipse会突然出现警告,但是这当然会导致难以调试的运行时错误。我不只在关键操作上下文中使用这种方法。

我可能误解了这个问题(一个示例和几行代码就好了),但是为什么您不总是使用合适的接口(和Java5+)呢?我看不出为什么你想要强制转换到HashMap而不是Map<KeyType,ValueType>。事实上,我想不出有什么理由将变量的类型设置为HashMap而不是Map。

为什么源是一个对象?是遗留集合的参数类型吗?如果是,请使用泛型并指定所需的类型。

下面是一个简短的示例,通过使用其他回答中提到的两种策略来避免“unchecked cast”警告。

Pass down the Class of the type of interest as a parameter at runtime (Class<T> inputElementClazz). Then you can use: inputElementClazz.cast(anyObject); For type casting of a Collection, use the wildcard ? instead of a generic type T to acknowledge that you indeed do not know what kind of objects to expect from the legacy code (Collection<?> unknownTypeCollection). After all, this is what the "unchecked cast" warning wants to tell us: We cannot be sure that we get a Collection<T>, so the honest thing to do is to use a Collection<?>. If absolutely needed, a collection of a known type can still be built (Collection<T> knownTypeCollection).

下面示例中的遗留代码接口在StructuredViewer中有一个属性“input”(StructuredViewer是一个树或表小部件,“input”是它背后的数据模型)。这个“输入”可以是任何类型的Java集合。

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();
}

当然,如果我们使用错误的数据类型的遗留代码(例如,如果我们将一个数组设置为StructuredViewer的“输入”而不是Java Collection),上面的代码就会给出运行时错误。

调用方法的例子:

dragFinishedStrategy.dragFinished(viewer, Product.class);

下面是重写equals()操作时的一种处理方法。

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);
    }
}

这似乎在Java 8中工作(甚至用-Xlint:unchecked编译)