2011-10-05 20 views
9

estoy golpeando una pared de ladrillo con la serialización de una subclase de Ubicación en Android/javasubclase de la clase Serializable padre que no serializable

ubicación no es serializable. Tengo una primera subclase llamada FALocation que no tiene variables de instancia. Lo he declarado serializable.

entonces tengo una llamada waypoint segunda clase que tiene este aspecto:

public class Waypoint extends FALocation implements Serializable { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

    /* Class variables *******************************************************/ 
    private static int CLASS_VERSION=1; //Used to version parcels 

    /* Instance variables ****************************************************/ 
    private transient String type=DataHelper.PT_TYPE_US; 
    private transient String country; 
    private transient String name=null; 
    private transient String description=null; 
    private transient int elevation = 0; 
    private transient int population = 0; // Afterthought, added to match the DB structure 

    /* Constructors **********************************************************/  
    public Waypoint() { 
     super(); 
    } 

    public Waypoint(double lat, double lon, String name, String description) { 
     super(lat, lon); 
     this.setName(name); 
     this.setDescription(description); 
    } 

    public Waypoint(Location l) { 
     super(l); 
    } 

    public Waypoint(String provider) { 
     super(provider); 
    } 


    /* Implementing serializable */ 
    private void writeObject(java.io.ObjectOutputStream out) throws IOException { 
     Log.v("DroidFA", "Serialising \"%s\" (v%d).", Waypoint.class.getSimpleName(), CLASS_VERSION); 
     out.writeInt(CLASS_VERSION); 

     out.writeObject(type); 
     out.writeObject(country); 
     out.writeObject(name); 
     out.writeObject(description); 
     out.writeInt(elevation); 
     out.writeInt(population); 
    } 

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { 

     int serialClassVersion = in.readInt(); 
     Log.v("DroidFA", "Deserialising \"%s\" (v%d).", Waypoint.class.getSimpleName(),serialClassVersion); 

     type = (String) in.readObject(); 
     country = (String) in.readObject(); 
     name = (String) in.readObject(); 
     description = (String) in.readObject(); 
     elevation = in.readInt(); 
     population = in.readInt(); 
    } 
} 

serialización funciona bien.

Deseriamization produce la excepción followwing (el objeto de la pierna contiene un waypoint) .:

10-05 13:50:35.259: WARN/System.err(7867): java.io.InvalidClassException: android.location.Location; IllegalAccessException 
10-05 13:50:35.267: WARN/System.err(7867):  at java.io.ObjectInputStream.resolveConstructorClass(ObjectInputStream.java:2010) 
10-05 13:50:35.267: WARN/System.err(7867):  at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:2095) 
10-05 13:50:35.267: WARN/System.err(7867):  at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:929) 
10-05 13:50:35.267: WARN/System.err(7867):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2285) 
10-05 13:50:35.278: WARN/System.err(7867):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2240) 
10-05 13:50:35.278: WARN/System.err(7867):  at com.droidfa.navigation.Leg.readObject(Leg.java:262) 
.../... 
+0

Parece que ese problema está en otro lado. com.droidfa.navigation.Leg.readObject (Leg.java:262) –

+0

La línea de la pierna 262 es: "from = (Waypoint) in.readObject();" que es donde realmente se encuentra el problema;). – jmc34

Respuesta

11

¿Es absolutamente necesario para serializar la ubicación? tal vez podrías marcarlo como transitorio y obtenerlo dinámicamente después de deserializar el objeto. (Anyway, from the documentation):

Q: Si la clase A no implementa Serializable, pero una subclase B implementa Serializable, serán los campos de la clase A ser serializados cuando se serializa B?

A: Solo se escriben y restauran los campos de objetos serializables. El objeto puede restaurarse solo si tiene un constructor no arg que inicializará los campos de supertipos no serializables. Si la subclase tiene acceso al estado de la superclase, puede implementar writeObject y readObject para guardar y restaurar ese estado.

lo tanto, si la subclase tiene acceso a los campos de su superclase no serializable (s) se puede usar el protocolo writeObject y readObject para implementar la serialización. De lo contrario, habrá campos que no se podrán serializar.

+0

Ok, puedo serializar los campos de ubicación de la subclase, pero el problema es que trata de deserializar la ubicación de todos modos. ¿Hay alguna forma de que pueda evitar que eso suceda desde la subclase? – jmc34

+0

Ok, tengo "pseudo" serielized mi subclase de ubicación del objeto adjunto. Resuelve el problema. Gracias. – jmc34

+0

"Tengo" pseudo "serielized mi subclase de ubicación del objeto adjunto." Hola, estoy enfrentando lo mismo, ¿podrían explicarme mejor? ¿Qué significa Pseudo aquí? –

1

Parece que la ubicación no tiene público/protegida sin argumentos constructor. Tal constructor es necesario para que esté disponible para la serialización en la subclase.

http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html dice:

Para permitir que los subtipos de clases no serializables a ser serializado, el subtipo puede asumir la responsabilidad de guardar y restaurar el estado de público del supertipo, protegido, y (si es accesible) paquete campos. El subtipo puede asumir esta responsabilidad solo si la clase se extiende tiene un constructor no arg accesible para inicializar el estado de la clase . Es un error declarar una clase Serializable si este no es el caso. El error se detectará en el tiempo de ejecución.

y lo mismo con las palabras de especificación de serialización:

Una clase Serializable debe hacer lo siguiente: ... tener acceso a la constructor sin argumentos de sus primeros superclase nonserializable

Eso explicaría por qué tiene problemas solo en la deserialización, porque naturalmente no se llama al constructor durante la serialización.

Pequeño ejemplo de resistencia, sin constructor accesible:

public class A { 
    public A(String some) {}; 
    private A() {} //as protected or public everything would work 
} 

public class B extends A implements Serializable { 
    public B() { 
     super(""); 
    } 
    //these doesn't really matter 
    //private void writeObject(java.io.ObjectOutputStream out) throws IOException { } 
    //private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { } 
} 

public class BSerializer { 

    public static void main(String ... args) throws Exception { 
     B b = new B(); 

     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(baos); 
     oos.writeObject(b); 
     ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 
     ObjectInputStream ois = new ObjectInputStream(bais); 
     B deserialized = (B) ois.readObject(); //InvalidClassException 
    } 
} 
+0

android.location.Location; IllegalAccessException se lanza cuando un programa intenta acceder a un campo o método al que no se puede acceder desde la ubicación donde se hace la referencia. –

+0

La ubicación de hecho no tiene un constructor público no arg. Pero, ¿a dónde debería ir desde allí? – jmc34

+0

Lamentablemente, entonces no puede serializarlo directamente. No puede hacer nada más que guardar el estado en otro lugar, tomar el estado guardado y construir una nueva Ubicación (o lo que sea que la amplíe). –

Cuestiones relacionadas