在我的spring应用程序上下文文件中,我有如下内容:

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
    <entry key="some_key" value="some value" />
    <entry key="some_key_2" value="some value" />   
</util:map>

在java类中,实现看起来像:

private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

在Eclipse中,我看到一个警告说:

类型安全:未检查从Object转换到HashMap<String,String>

出了什么问题?


当前回答

我做错了什么?如何解决这个问题?

在这里:

地图<字符串,字符串> someMap =(文件夹<字符串,字符串>)getApplicationContext(“someMap”);

你使用一个我们通常不希望使用的遗留方法,因为它返回Object:

Object getBean(String name) throws BeansException;

从bean工厂获取(单例)/创建(原型)bean的方法是:

<T> T getBean(String name, Class<T> requiredType) throws BeansException;

使用它,如:

Map<String,String> someMap = app.getBean(Map.class,"someMap");

将编译,但仍然带有未检查的转换警告,因为所有Map对象不一定是Map<String, String>对象。

但是<T> T getBean(字符串名称,类<T> requiredType)抛出BeansException;在bean泛型类(如泛型集合)中是不够的,因为这需要指定多个类作为参数:集合类型及其泛型类型。

在这种情况下以及一般情况下,更好的方法是不直接使用BeanFactory方法,而是让框架注入bean。

bean声明:

@Configuration
public class MyConfiguration{

    @Bean
    public Map<String, String> someMap() {
        Map<String, String> someMap = new HashMap();
        someMap.put("some_key", "some value");
        someMap.put("some_key_2", "some value");
        return someMap;
    }
}

注豆:

@Autowired
@Qualifier("someMap")
Map<String, String> someMap;

其他回答

首先,使用新的HashMap创建调用是在浪费内存。第二行完全忽略了对这个创建的hashmap的引用,从而使垃圾收集器可以使用它。所以,不要这样做,使用:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

其次,编译器抱怨您将对象强制转换为HashMap,而没有检查它是否是HashMap。但是,即使你要做:

if(getApplicationContext().getBean("someMap") instanceof HashMap) {
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}

您可能仍然会得到这个警告。问题是,getBean返回Object,所以不知道是什么类型。直接将其转换为HashMap不会导致第二种情况的问题(也许在第一种情况下不会有警告,我不确定Java编译器对Java 5的警告有多严格)。然而,您正在将其转换为HashMap<String, String>。

HashMap是一种以对象为键并以对象为值的映射,HashMap< object object >。因此,当您获得bean时,不能保证它可以表示为HashMap<String, String>,因为您可以使用HashMap<Date, Calendar>,因为返回的非泛型表示可以有任何对象。

如果代码被编译,你可以执行String value = map.get("thisString");如果没有任何错误,不要担心这个警告。但是,如果映射不完全是字符串键到字符串值,则将在运行时得到ClassCastException,因为泛型在这种情况下无法阻止这种情况的发生。

警告就是这样。一个警告。有时警告无关紧要,有时则不然。它们用来提醒你注意编译器认为可能是问题,但可能不是问题的东西。

在类型转换的情况下,它总是会给出一个警告。如果你绝对确定一个特定的强制转换是安全的,那么你应该考虑在行之前添加一个这样的注释(我不确定语法):

@SuppressWarnings (value="unchecked")

您得到这条消息是因为getBean返回了一个Object引用,并且您正在将它强制转换为正确的类型。Java 1.5给出了一个警告。这就是使用Java 1.5或更高版本代码的本质。Spring有类型安全版本

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");

在待办事项清单上。

问题是强制转换是一个运行时检查-但由于类型擦除,在运行时,对于任何其他Foo和Bar, HashMap<String,String>和HashMap<Foo,Bar>之间实际上没有区别。

使用@SuppressWarnings(“未选中”),捏住鼻子。哦,还有在Java中为具体化泛型发起的运动:)

如上面的消息所示,List不能区分List<Object>和List<String>或List<Integer>。

我已经解决了类似问题的错误信息:

List<String> strList = (List<String>) someFunction();
String s = strList.get(0);

与以下:

List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);

解释:第一个类型转换验证对象是一个List,而不关心其中持有的类型(因为我们不能在List级别验证内部类型)。现在需要进行第二次转换,因为编译器只知道List包含某种类型的对象。这将在访问List时验证每个对象的类型。