2009-10-22 7 views
5
public Configuration(Node node, File file) { 
    HashMap<String, String> conf = (HashMap<String, String>) SerializationUtils.deserialize(new FileInputStream(file)); 
} 

entiendo por qué esto da una advertencia fundido insegura, pero ¿cuál es la mejor manera/aceptada de hacer esto con seguridad? ¿Hay alguna buena manera?molde genérico inseguro al deserializar una colección

Respuesta

2

No puede manejar esta situación de una manera totalmente segura utilizando solo el lenguaje Java.

Debido a que esto es algo que tiene que ser hecho en varias ocasiones y realmente no se puede conseguir alrededor de él, se sugiere emplear un método genreic ay leer y emitir objetos genéricos:

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

Sin embargo, sugiero que generalmente no usas métodos como este para suprimir las advertencias válidas.

+0

De eso tenía miedo; solo esperaba que me faltara algo:/ –

+0

¡Es una advertencia válida solo en el contexto de un diseño de función de idioma quebrado! –

+1

Si no fuera por el borrado de tipo, no podríamos deserializar estos objetos. Creo que es una victoria –

2

En realidad no hay ninguna manera de hacer esto correctamente porque la información de tipo en tiempo de compilación que desea comprobar (es decir String) no está disponible en tiempo de ejecución, (es decir, cuando el elenco que realmente ocurre) a través del proceso conocido como borrado . Creo que la mejor manera es para que usted pueda pasar su colección deserializado a través de un poco de "corrector" a medida:

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

donde:

@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 
} 
+0

¿Alguien quiere dilucidar por qué una respuesta perfectamente válida y correcta ha sido downvoted? ¿Es porque * I * rechazó una respuesta inválida e incorrecta por casualidad? –

+0

No fui el menos votante, pero puedo ver que esto puede no funcionar en el caso de, por ejemplo, acceso multiproceso. Un hilo ejecuta el corrector, mientras que otro utiliza la referencia original para insertar el tipo "incorrecto" después del control. Boom, ClassCastException. –

+0

@Steven - No creo que * "pueda ser inseguro en un entorno de subprocesos múltiples" * es necesariamente un error con este enfoque de "verificación". He agregado un poco más de detalle a mi respuesta. El método simplemente no está diseñado para funcionar de esta manera y podría documentarse así –

1

Para construir en la respuesta anterior, suelo ir un poco más lejos al suprimir advertencias. Puse la anotación en una variable local en lugar del método, para reducir el alcance de la supresión. Esto significa que si alguien viene y aumenta el método más tarde, no habrá una supresión involuntaria. Agrega otra línea de código, pero creo que la compensación vale la pena.

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

Lamentablemente no se puede agregar una anotación a una expresión (al menos no todavía).

+0

Tiendo a poner la anotación en el método, porque el objetivo del método es suprimir una advertencia. –

Cuestiones relacionadas