Небезопасное обобщение типов при десериализации коллекции - PullRequest
6 голосов
/ 23 октября 2009
public Configuration(Node node, File file) {
    HashMap<String, String> conf = (HashMap<String, String>) SerializationUtils.deserialize(new FileInputStream(file));
}

Я понимаю , почему это дает опасное предупреждение, но каков наилучший / приемлемый способ сделать это безопасно? Есть ли хороший способ?

Ответы [ 3 ]

2 голосов
/ 23 октября 2009

На самом деле нет никакого способа сделать это должным образом, потому что информация о типе времени компиляции, которую вы хотите проверить (т.е. String), недоступна во время выполнения (т.е. когда фактически происходит приведение) через процесс, известный как * 1002. * стирание . Я думаю, что для вас лучший способ передать свою десериализованную коллекцию через какую-то сделанную на заказ «шашку»:

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 голосов
/ 23 октября 2009

Вы не можете справиться с этой ситуацией полностью безопасным для типов способом, используя только язык Java.

Поскольку это нужно делать неоднократно, и вы не можете обойти это, я предлагаю использовать общий метод для чтения и приведения общих объектов:

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

Однако я предлагаю, чтобы вы обычно не использовали подобные методы для подавления действительных предупреждений.

1 голос
/ 23 октября 2009

Чтобы развить более ранний ответ, я обычно иду немного дальше, подавляя предупреждения. Я поместил аннотацию на локальную переменную вместо метода, чтобы уменьшить область подавления. Это означает, что если кто-то придет позже, дополнит метод, не будет непреднамеренного подавления. Это добавляет еще одну строку кода, но я думаю, что компромисс стоит.

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

К сожалению, вы не можете добавить аннотацию к выражению (по крайней мере, пока).

...