2012-02-23 19 views
6

Tuve que serializar un objeto complejo, pero uno de sus componentes no era serializable (un objeto de gráfico de terceros), así que creé una versión serializable personalizada de esta clase Graph y utilizó la transformación de lista Guava para convertir el objeto no serializable a los objetos personalizados. La serialización writeObject aún falló. Me interesaría saber por qué? Mi suposición es que Lists.transform realiza su operación perezosamente (sosteniendo una referencia oculta al objeto original)Problemas de serialización de Java, al usar guava Lists.transform

¿Existe una solución para este problema?

Respuesta

11

Lists.transform() funciona con holgazanería como sospechabas. Se podría hacer una de

Lists.newArrayList(Lists.transform(...)) 

o, si quieres una versión inmutable,

ImmutableList.copyOf(Lists.transform(...)) 

y luego serializar la lista resultante.

+0

No tiene para crear una nueva lista, vea @eneveu answer. – Xaerxess

+2

El OP indicó que fromList estaba específicamente lleno de elementos no serializables. –

+1

@Xaerness ¿puedes modificar tu comentario? No se puede obtener una lista serializable simplemente usando el enum trick (respuesta @eneveu). Esta respuesta es la más útil con respecto a la pregunta. –

1

Si intentó serializar una lista devuelta desde la transformación de Lists #, la lista de interfaz en sí es no Serializable.

+1

¿Por qué sería un problema? Es la implementación que se considera durante la serialización. Y la implementación devuelta por Lists.transform() implementa Serializable: "La lista devuelta siempre implementa Serializable, pero la serialización tendrá éxito solo cuando fromList y la función sean serializables". (del [javadoc] (http://docs.guava-libraries.googlecode.com/git-history/v11.0.1/javadoc/com/google/common/collect/Lists.html)) –

6

Lists.transform() devuelve una vista transformada de la lista original. Desde el Lists.transform() javadoc:

La lista devuelta siempre implementa Serializable, pero serialización tendrá éxito sólo cuando fromlist y función son serializable.

Al serializar la vista transformada, en realidad está serializando la lista original, más la función. En su caso, falla porque su lista original no es serializable (porque contiene elementos gráficos no serializables). Pero también podría fallar porque la función no implementa serializable.

Por cierto, hay un pequeño truco para crear funciones serializables sin la verborrea. En vez de hacer:

private static final class MyFunction extends Function<String, String> implements Serializable { 
    private static final MyFunction INSTANCE = new MyFunction(); 

    @Override 
    public String apply(String input) { 
     return "[" + input + "]"; 
    } 

    private Object readResolve() { 
     return INSTANCE; 
    } 
    private static final long serialVersionUID = 1; 
    } 

Puede utilizar el patrón Singleton enumeración, lo cual es mucho menos detallado, y le consigue la serialización de libre (ya que las enumeraciones son serializable). También se asegura de que su función sea singleton:

// enum singleton pattern 
    private enum MyFunction implements Function<String, String> { 
    INSTANCE; 

    @Override 
    public String apply(String input) { 
     return "[" + input + "]"; 
    } 
    } 
+2

Impresionante ... Java efectiva. Gracias. –

+1

Sí, Joshua Bloch explica en Effective Java que es la mejor manera de crear un singleton. Una enumeración es serializable, no es vulnerable a varios ataques de deserialización, y la JVM garantiza su unicidad. Puede encontrar buenos ejemplos del patrón en la biblioteca de Guava: http://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/base/Functions.java # 59 –

+0

Puntos de bonificación por citar EJ y por aplicaciones de buenos patrones en Guava, incluso si la respuesta no es eso es útil porque 'fromList' no va a ser serializable. –

Cuestiones relacionadas