расширяет сериализуемый геопоинт - не может прочитать объект обратно в - PullRequest
2 голосов
/ 11 января 2012

Мне нужно сериализовать список GeoPoints, а затем прочитать их обратно. Я искал в Интернете и обнаружил, что могу реализовать свой собственный GeoPoint и реализовать сериализуемый. Это работает, и я могу записать объект в файл .ser, но когда я читаю его обратно, я получаю недопустимое исключение класса, которое приводит к подробному сообщению - незаконное исключение исходного объекта GeoPoint. Я предполагаю, что неправильно расширяю GeoPoint в классе MyGeoPoint. может кто-нибудь взглянуть и сказать мне, где я делаю ошибку?

import com.google.android.maps.GeoPoint;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class MyGeoPoint extends GeoPoint implements Serializable {
static final long serialVersionUID = -3010695769693014199L;


public MyGeoPoint(int latitude, int longitude){
    super(latitude, longitude);
}
public MyGeoPoint(){
    this(0,0);
}
private void writeObject(ObjectOutputStream s) throws IOException{
    s.defaultWriteObject();
}
private void readObject(ObjectInputStream s)
        throws java.io.IOException, java.lang.ClassNotFoundException{
    s.defaultReadObject();
}
}

а потом привыкает как

File filex = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +"floodData.ser");
    MyGeoPoint aPoint = new MyGeoPoint();
    MyGeoPoint readPoint = null;
    //write
    try{
    FileOutputStream f = new FileOutputStream(filex);
    ObjectOutputStream s = new ObjectOutputStream(f);
    s.writeObject(aPoint);
    s.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    //read
    try {
    FileInputStream ff = new FileInputStream(filex);
    ObjectInputStream ss = new ObjectInputStream(ff);
    readPoint = (MyGeoPoint)ss.readObject();
    ss.close();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } 
    catch (Exception e) {
        e.printStackTrace();
    } 
    //end serialisationtest 

Ответы [ 4 ]

4 голосов
/ 11 января 2012

Проблема в том, что GeoPoint не имеет конструктора без аргументов, см. JavaDoc Сериализуемый :

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

И JavaDoc InvalidClassException

Выдается, когда среда выполнения сериализации обнаруживает одну из следующих проблем сКласс.

  • Последовательная версия класса не соответствует версии дескриптора класса, считанного из потока
  • Класс содержит неизвестные типы данных
  • класс не имеет доступного конструктора без аргументов
1 голос
/ 10 ноября 2012

Вам не нужно расширять com.google.android.maps.GeoPoint, чтобы иметь сериализуемый объект для хранения координат широты и долготы.

И поскольку вы не являетесь владельцем исходного объекта, вам не следует этого делать, потому что, если Google решит изменить исходную GeoPoint и скажем ... добавлять / удалять методы, изменять сигнатуры методов и т. Д. ... вы можете попасть в неприятности.

Что еще хуже, ваш код не будет переносимым, FYI Android на Kindle Fire не имеет доступа к API Карт Google, поэтому ваше приложение, начиная с com.google.android.maps.GeoPoint, не будет работать.

Для этого нужно создать Сериализуемый POJO с теми же точными свойствами (и его типами) для хранения координат широты / долготы, которые вы будете сериализовать:

package com.yourapp.beans;

public class YourGeoPoint implements Serializable {

        private static final long serialVersionUID = -99127398709809L;

        private int latitudeE6;
        private int longitudeE6;

        public YourGeoPoint() {
            this.setLatitudeE6(0);
            this.setLongitudeE6(0);
        }

        public YourGeoPoint(int latitudeE6, int longitudeE6) {
            this.setLatitudeE6(latitudeE6);
            this.setLongitudeE6(longitudeE6);
        }

        public int getLatitudeE6() {
            return latitudeE6;
        }

        public void setLatitudeE6(int latitudeE6) {
            this.latitudeE6 = latitudeE6;
        }

        public int getLongitudeE6() {
            return longitudeE6;
        }

        public void setLongitudeE6(int longitudeE6) {
            this.longitudeE6 = longitudeE6;
        }

    }

Тогда всякий раз, когда вам нужен com.google.android.maps.GeoPoint ... и после десериализации вашего экземпляра GeoPoint, просто выполните:

import com.google.android.maps.GeoPoint;
import com.yourapp.beans.YourGeoPoint;
//...    
YouGeoPoint yourGeoPoint = // De-serialization...        
GeoPoint geoPoint = new GeoPoint(yourGeoPoint.getLatitudeE6(), yourGeoPoint.getLongitudeE6());

Это работает на 100%, и ваш код будет переносимым на устройства Android, где API Google Maps не существует ... в этом случае просто импортируйте все библиотеки карт, к которым у вас есть доступ (например, ESRI или OpenSignalMaps) и получите одну из их «GeoPoints» или эквивалентный объект с координатами, исходящими от вашего собственного десериализованного объекта.

Ура!

0 голосов
/ 24 января 2015

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

private double lat;
private double lng;

public LatLng getLocation() {
    LatLng latLng = new LatLng(this.lat, this.lng);

    return latLng;
}

public void setLocation(LatLng location) {

    this.lat = location.latitude;
    this.lng = location.longitude;
}
0 голосов
/ 08 августа 2012

Просто чтобы сделать этот ответ более полным, я попытался решить проблему с помощью исправления бинтаида. Попробуйте добавить следующие строки в класс writeObject и readObject ...

private void writeObject(ObjectOutputStream s) throws IOException{
    s.writeInt(this.getLatitudeE6());
    s.writeInt(this.getLongitudeE6());
}
private void readObject(ObjectInputStream s)
        throws java.io.IOException, java.lang.ClassNotFoundException{
    this(s.readInt(), s.readInt());
}
...