为什么实现Serializable的对象的序列化会引发异常?

时间:2016-08-05 07:32:01

标签: java android serialization

我试图通过Intent将两个ArrayLists传递给另一个活动。创建了这个类来存储这两个数组。

public class StorageBin implements Serializable {
    //storage variables
    public ArrayList<String> placesList;
    public ArrayList<LatLng> latLngArrayList;

    public void storeData(ArrayList<String> names, ArrayList<LatLng> locations) {
        placesList = names;
        latLngArrayList = locations;
    }
}

我按照以下方式将它们置于意图中。

            StorageBin storageBin = new StorageBin();
            storageBin.storeData(placesList, latLngArrayList);
            intent.putExtra("storedData", storageBin);

最后一行导致以下异常。我做错了什么?

   FATAL EXCEPTION: main
   Process: lt.wilkas.isimintinosvietoves, PID: 24702
   java.lang.RuntimeException: Parcelable encountered IOException writing
   serializable object (name = lt.wilkas.isimintinosvietoves.MainActivity$StorageBin)
   at android.os.Parcel.writeSerializable(Parcel.java:1468)
   ...

1 个答案:

答案 0 :(得分:3)

我强烈怀疑这是因为您的MainActivity类不可序列化(因为它未声明为Serializable,或者它具有不可序列化的字段值),并且StorageBin是内部类(即嵌套但不是静态的)。

尝试制作StorageBin静态:

public static class StorageBin ...

为什么不是静态会破坏可串行化的原因是StorageBin有一个隐藏的MainActivity引用:这是允许您引用MainActivity上的实例方法(或{ {1}}在MainActivity.this。{/ p>的正文中

很多时候,这个引用是不必要的:它不仅会破坏序列化,还会导致内存泄漏,因为它会阻止StorageBin实例被垃圾回收。

始终制作嵌套类MainActivity,除非他们确实需要这样做。

如果您使用LatLng class也阻止了序列化(因为它没有实现static),您有两种选择:

  • 停止使用Serializable类,并使用可序列化的类型;
    • 在您的公开API中,以便LatLng接受其他类型的列表
    • 使您的公开API看起来使用storeData,但随后在内部转换为可序列化类型
  • 标记LatLng字段latLngArrayList,并使用transientwriteObject分别提供自定义序列化和反序列化逻辑。

    例如,您可以将坐标序列化为数组,并在反序列化时重建readObject实例:

    LatLng

请注意,实施private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); double[] coords = new double[2 * latLngArrayList.size()]; int i = 0; for (LatLng latLng : latLngArrayList) { coords[2*i+0] = latLng.latitude; coords[2*i+1] = latLng.longitude; ++i; } out.writeObject(coords); } private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { in.defaultReadObject(); double[] coords = (double[]) in.readObject(); // + Check that coords.length is even. latLngArrayList = new ArrayList<>(coords.size() / 2); for (int i = 0; i < coords.size(); i += 2) { latLngArrayList.add(new LatLng(coords[i], coords[i+1])); } } 并不能保证可串行化。你可以轻松写一堂课:

Serializable

并编译好。如果class MyClass implements Serializable { NonSerializableType field } 为空,可能序列化。或者,如果它是field的子类的实例,它实现了NonSerializableType

我不想说序列化是一种猜谜游戏,因为如果正确使用它显然有效;它很难保证你正确使用它。