类实现Serializable

时间:2017-07-27 16:44:22

标签: java android serialization

TL; DR

当我尝试反序列化PullSheet对象(下面的类)时,我得到了一个java.io.NotSerializableException。我哪里错了?

编辑:在问题类中添加一个空构造函数后,我现在得到一个"不兼容的"异常。

StackTrace:

java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:606)
java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1772)
java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
com.campusden.learning.movingdata.ScannerActivity.loadSheet(ScannerActivity.java:271)
com.campusden.learning.movingdata.ScannerActivity.onCreate(ScannerActivity.java:79)
android.app.Activity.performCreate(Activity.java:6679)
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
android.app.ActivityThread.-wrap12(ActivityThread.java)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:154)
android.app.ActivityThread.main(ActivityThread.java:6119)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

问题

我正在尝试序列化PullSheet对象,以便存储简单的数据备份,并将其作为用户的功能要求。我能够毫无例外地序列化对象,但是当我尝试反序列化时,我在PullItem类上得到了一个java.io.NotSerializableException。

代码

PullSheet.java

import ...

public class PullSheet implements Serializable{

protected String pullerName;
protected String role;
protected String store;
protected String sheetId;
protected String runItId;
protected String date;
protected UUID uuid;
protected String serialName;
protected Long startTime = System.currentTimeMillis();
protected ArrayList<PullItem> SheetItems = new ArrayList<PullItem>();


public void createSheet(String _pullerName, String _role, String _store, String _runItId){
    setPullerName(_pullerName);
    setRole(_role);
    setStore(_store);
    setRunItId(_runItId);
    setSerialName();
    setDate();
    setUuid();
    setSheetId();
}

protected void addItem(String sku, Integer qty){
    SheetItems.add(new PullItem(sku, qty));
}
protected void removeItem(PullItem item){
    this.SheetItems.remove(item);
}

//Getters and setters

public String getPullerName(){ return pullerName; }
public String getRole(){ return role; }
public String getStore(){ return store; }
public String getRunItId(){ return runItId; }
public String getSheetId(){ return sheetId; }
public Long getStartTime(){ return startTime; }
public UUID getUuid() { return uuid; }


private void setPullerName(String _pullerName){ pullerName = _pullerName; }
private void setRole(String _role){ pullerName = _role; }
private void setStore(String _store){ store = _store; }
private void setRunItId(String _runItId){ runItId = _runItId; }
private void setSerialName(){ serialName = this.store + "-" + this.date + "_" + this.uuid; }
private void setUuid(){ uuid = UUID.randomUUID(); }
private void setDate() {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
    this.date = formatter.format(new Date(this.startTime));
}

private void setSheetId(){

    String randUUID = uuid.toString();
    sheetId = this.date + "-" + this.store + "-" + this.pullerName + "-" + randUUID + "-" + this.runItId;

}

}

PullItem.java

import ...

public class PullItem implements Serializable {

protected String sku;
protected Integer qty;


public PullItem(String sku, Integer qty) {
    setSku(sku);
    setQty(qty);
}

public PullItem(String sku) {
    setSku(sku);
    this.qty = 1;
}


String getSku(){
    return sku;
}

Integer getQty(){
    return qty;
}

void setSku(String _sku){
    sku = _sku;
}

void setQty(Integer _qty){
    qty = _qty;
}
void incrementQty(){
    qty += 1;
}
}

序列化和反序列化PullSheet对象的函数:

public static boolean saveSheet(Context context, PullSheet sheet){
    String fileName = "saved.szs";
    try {
        FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        Log.d("rep", fileName);
        oos.writeObject(sheet);
        oos.close();
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }

    return true;
}

public static PullSheet loadSheet(Context context, String fileName) {
    try {
        FileInputStream fis = context.openFileInput(fileName);
        ObjectInputStream is = new ObjectInputStream(fis);
        Object readObject = is.readObject();
        is.close();

        if(readObject != null && readObject instanceof PullSheet) {
            return (PullSheet) readObject;
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    return null;
}

我需要什么

请让我知道我哪里出错了。我假设它不是导致异常的类型,因为所有类都实现了Serializable,但我可能会关闭。在此先感谢您的任何帮助

2 个答案:

答案 0 :(得分:2)

虽然该类可以实现Serializable,但这意味着其中的每个字段[1]都必须是:

  • 可序列化或
  • 瞬态

实例UUID(类中的字段)的含义。这可序列化吗?您班上的每个领域都必须实现Serializable。如果它们不实现可序列化,则必须为transient。如果它是静态或最终字段,则不必如此。静态和最终字段无论如何都不是序列化的。

[1]:每个字段表示可序列化的每个字段。这将排除最终和静态字段,或标记为瞬态的字段

工作示例:

(提及的所有字段都很重要,对于此示例而言,这些字段不是静态的,最终的或瞬态的)

  • Class1实现Serializable。具有Class2,Class3,int,double和ArrayList
  • 类型的字段
  • Class2实现Serializable具有COntext
  • 类型的字段
  • Class3实现serializable具有int,double,Class2
  • 类型的字段

序列化Class1会导致异常。让我们快点解决这个问题:

  • Class2可序列化
  • Class3可序列化
  • int是可序列化的
  • double是可序列化的
  • ArrayList(can)可序列化,如果它所持有的类是可序列化的
  • 上下文不可序列化

因为Class2有一个Context字段(不可序列化)并且与Class1一起序列化(因为Class1有一个Class2类型的字段),你最终会得到一个异常

答案 1 :(得分:1)

序列化时没有实现Serializable。那时你有一个例外。您修复它以实现Serializable。然后,您尝试反序列化旧流。它不起作用。

修改

  

在问题类中添加一个空构造函数后,我现在遇到“不兼容”的异常。

因为您更改了隐式serialVersionUIDSerializable类中不需要空构造函数。

编辑2

这里的一些人似乎并不知道当你尝试序列化一个不可序列化的对象时,NotSerializableException被抛出(1)并且(2)被写入数据流中,当你到达时在使用readObject()进行读取时,它会再次被抛出,完全如OP的堆栈跟踪所示。