反序列化集合时不安全的通用转换

时间:2009-10-22 21:03:58

标签: java generics serialization casting

public Configuration(Node node, File file) {
    HashMap<String, String> conf = (HashMap<String, String>) SerializationUtils.deserialize(new FileInputStream(file));
}

我理解为什么这会给出不安全的演员警告,但是安全地做到这一点的最佳/可接受方式是什么?有什么好办法吗?

3 个答案:

答案 0 :(得分:2)

您无法仅使用Java语言以完全类型安全的方式处理这种情况。

因为这是必须重复进行的事情而你无法真正解决它,我建议使用一种genreic方法来读取和转换泛型对象:

@SuppressWarnings("unchecked")
public static <T> T readObject(
    ObjectInputStream in
) throws IOException, ClassNotFoundException {
    return (T)in.readObject();
}

但是,我建议你通常不要使用这样的方法来抑制有效的警告。

答案 1 :(得分:2)

实际上没有任何方法可以正确执行此操作,因为您要检查的编译时类型信息(即String)在运行时不可用(即,当实际执行转换时)通过称为的擦除即可。我认为最好的方法是通过一些定制的“检查器”传递反序列化的集合:

Map<?,?> conf = deserialize(rsrc);
Map<String, String> checked = checkMap(conf, String.class, String.class);
//can use checked freely

其中:

@SuppressWarnings("unchecked")
public static <K, V> Map<K,V> checkMap(Map<?,?> map, Class<? extends K> k, Class<? extends V> v) {
    for (Map.Entry<?, ?> e : map) {
        k.cast(e.getKey());   //will throw ClassCastException
        v.cast(e.getValue());
    }
    return (Map<K,V>) map; //unchecked 
}

答案 2 :(得分:1)

在早期答案的基础上,我通常会在抑制警告时更进一步。我将注释放在局部变量而不是方法上,以减少抑制的范围。这意味着如果有人在以后增加该方法,则不会有无意的抑制。它确实添加了另一行代码,但我认为权衡是值得的。

public static <T> T readObject(
    ObjectInputStream in
) throws IOException, ClassNotFoundException {
    @SuppressWarnings("unchecked")
    T val = (T)in.readObject();
    return val;
}

不幸的是,你无法在表达式中添加注释(至少现在还没有)。