2011-10-05 2 views
9

Я ударять BrickWall с сериализации подкласса Место в Android/JavaСериализуемый подкласс не сериализуемым родительского класса

Место не сериализации. У меня есть первый подкласс, называемый FALocation, который не имеет никаких переменных экземпляра. Я объявил это сериализуемым.

Тогда у меня есть второй класс с именем Точка, которая выглядит следующим образом:

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(); 
    } 
} 

Сериализация работает нормально.

Deseriamization производит исключение followwing (объект ножка содержит точку) .:

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

Кажется, эта проблема находится где-то в другом месте. com.droidfa.navigation.Leg.readObject (Leg.java:262) –

+0

Линия ноги 262: «from = (Waypoint) in.readObject();» где и лежит проблема;). – jmc34

ответ

11

Это абсолютно необходимо сериализовать Расположение? возможно, вы могли бы отметить его как переходный процесс и получить его динамически после десериализации объекта. (Anyway, from the documentation):

Q: Если класс А не реализует Serializable, но подкласс B реализует Serializable, будут поля класса А сериализации, когда B сериализации?

A: Выделяются и восстанавливаются только поля объектов Serializable. Объект может быть восстановлен, только если он имеет конструктор no-arg, который будет инициализировать поля несериализуемых супертипов. Если подкласс имеет доступ к состоянию суперкласса, он может реализовать writeObject и readObject для сохранения и восстановления этого состояния.

Таким образом, если подкласс имеет доступ к полям его несериализуемого суперкласса (ов), он может использовать протокол writeObject и readObject для реализации сериализации. В противном случае появятся поля, которые невозможно будет сериализовать.

+0

Хорошо, я могу сериализовать поля Location из подкласса, но проблема в том, что он пытается десериализовать местоположение в любом случае. В любом случае, я могу остановить это из подкласса? – jmc34

+0

Хорошо, у меня есть «псевдо» serielized мой подкласс Location из окружающего объекта. Решила проблему. Благодарю. – jmc34

+0

«У меня есть« псевдо »serielized мой подкласс Location из закрывающего объекта». Привет, я смотрю то же самое, не могли бы вы рассказать. Что означает здесь Pseudo? –

1

Похоже Место не имеет публичный/не защищен конструктор без аргументов. Такой конструктор необходим, чтобы сделать его доступным для сериализации в подклассе.

http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html говорит:

Чтобы подтипы несериализуемых классов для сериализации, то подтипа может взять на себя ответственность за сохранение и восстановления состояния публики супертипа, в защите, и (если доступно) пакет полей. Подтип может взять на себя эту ответственность, только если класс , который он расширяет, имеет доступный конструктор no-arg для инициализации состояния класса . Ошибка объявить класс Serializable, если это не так. Ошибка будет обнаружена во время выполнения.

И то же самое со словами из спецификации сериализации:

сериализации класс должен сделать следующее: ... иметь доступ к конструктор без аргументов из первых nonserializable суперкласса

Это объясняет, почему у вас проблемы только при десериализации, потому что в процессе сериализации естественный конструктор не вызывается.

Небольшой пример неудачу без доступного конструктора:

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 вызывается, когда программа пытается получить доступ к полю или методу, который недоступен из того места, где делается ссылка. –

+0

Местоположение действительно не имеет конструктора public arg. Но куда мне идти? – jmc34

+0

К сожалению, вы не можете сериализовать его напрямую. Вы не можете ничего сделать, кроме сохранения состояния в другом месте, сохранения состояния и создания нового местоположения (или того, что его расширяет). –