代码之家  ›  专栏  ›  技术社区  ›  Steven Schlansker

反序列化集合时出现不安全的泛型强制转换

  •  6
  • Steven Schlansker  · 技术社区  · 15 年前
    public Configuration(Node node, File file) {
        HashMap<String, String> conf = (HashMap<String, String>) SerializationUtils.deserialize(new FileInputStream(file));
    }
    

    我理解 为什么? 这会给出一个不安全的演员警告,但是什么是最好的/公认的安全方式呢?有什么好办法吗?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Tom Hawtin - tackline    15 年前

    不能只使用Java语言以完全类型安全的方式处理这种情况。

    因为这是必须重复执行的操作,您不能真正绕过它,所以我建议使用genreic方法来读取和强制转换泛型对象:

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

    但是,我建议您一般不要使用这样的方法来禁止有效的警告。

        2
  •  2
  •   oxbow_lakes    15 年前

    实际上没有任何方法可以正确地执行此操作,因为您要检查的编译时类型信息(即 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 
    }
    
        3
  •  1
  •   dstine    15 年前

    为了建立在前面的答案的基础上,我通常在抑制警告时做得更进一步。我将注释放在局部变量上而不是方法上,以减小抑制的范围。这意味着,如果以后有人来扩充这个方法,就不会有无意的抑制。它确实添加了另一行代码,但我认为这种折衷是值得的。

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

    不幸的是,您无法将注释添加到表达式中(至少尚未添加)。