java - 尝试将可序列化对象写入文件时出现 NotSerializedException

标签 java android serialization android-7.0-nougat

我在 Android 上,尝试将对象列表保存到文件中,但总是遇到此异常:java.io.NotSerializedException: android.app.Application。 p>

我试图找出可能导致此问题的原因,但我发现的只是在尝试序列化 Context 对象时引发此错误,但我什至没有尝试序列化与应用程序相关的任何内容或上下文

DataFileManager.java

public class DataFileManager implements Serializable {
    public static final String FILE_NAME = "circles.dat";
    private transient final Context ctxt;
    private Set<Save> saves;
    public DataFileManager(Context ctxt) {
        this.ctxt = ctxt;
        this.saves = new HashSet<>();
        reloadSaves();
    }

    public void reloadSaves() {
        File file = file();
        if(file.exists()) {
            try (ObjectInputStream reader = new ObjectInputStream(
                    new BufferedInputStream(ctxt.openFileInput(FILE_NAME)))) {
                saves.clear();
                try {
                    while (true) {
                        Save save = (Save) reader.readObject();
                        saves.add(save);
                    }
                } catch(EOFException e) {
                } finally {
                    reader.close();
                }
            } catch (IOException | ClassNotFoundException e) {
                Log.e(e.getClass().getName(), "", e);
            }
        } else
            Log.e("load", "file does not exist");
    }

    private void save() {
        try {
            file().createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(e.getClass().getName(), "", e);
        }
        try (ObjectOutputStream writer = new ObjectOutputStream(new BufferedOutputStream(ctxt.openFileOutput(FILE_NAME, Context.MODE_PRIVATE)))) {
            Iterator<Save> iter = saves.iterator();
            while(iter.hasNext()) {
                Save save = iter.next();
                writer.writeObject(save);
            }
            writer.flush();
            writer.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Log.e(e.getClass().getName(), "", e);
        } catch (IOException e) {
            Log.e(e.getClass().getName(), "", e);
        }
    }


    private File file() {
        return ctxt.getFileStreamPath(FILE_NAME);
    }


    public Save save(String saveName, Set<Circle> circles) throws SaveAlreadyExistsException {
        if(exists(saveName))
            throw new SaveAlreadyExistsException();
        Save save = createSave(saveName, circles);
        if(!saves.add(save))
            throw new SaveAlreadyExistsException();
        return save;
    }

    public Save forceSave(String saveName, Set<Circle> circles) throws UnknownSaveException {
        Save save;
        if(exists(saveName))
            (save = find(saveName)).overwrite(circles);
        else {
            save = createSave(saveName, circles);
            if(!saves.add(save)) {
                saves.remove(save);
                if(!saves.add(save))
                    throw new UnknownSaveException("Couldn't add Save object to the list");
            }
            save();
        }
        return save;
    }

    private Save createSave(String name, Set<Circle> circles) {
        Save save = new Save(name);
        save.circles.addAll(circles);
        return save;
    }

    public boolean exists(String saveName) {
        return saves.stream().anyMatch(s -> s.getName().equals(saveName));
    }

    public boolean existsIgnoreCase(String saveName) {
        return saves.stream().anyMatch(s -> s.getName().equalsIgnoreCase(saveName));
    }

    public Save find(String saveName) {
        return saves.stream().filter(s -> s.getName().equals(saveName)).findFirst().orElse(null);
    }

    public List<Save> search(String query) {
        return saves.stream().filter(s -> s.getName().toLowerCase().contains(query.toLowerCase()))
                    .collect(Collectors.toList());
    }

    public Set<Save> getSaves() {
        return Collections.unmodifiableSet(saves);
    }



    public class Save implements Serializable {
        private final String      name;
        private final Set<Circle> circles;

        private Save(String name) {
            this.name = name;
            circles = new HashSet<>();
        }

        public boolean overwrite(Set<Circle> circles) {
            if (circles != null && circles.size() > 0) {
                this.circles.clear();
                this.circles.addAll(circles);
                save();
                return true;
            }
            return false;
        }

        public Set<Circle> getCircles() {
            return circles.stream().map(Circle::clone).collect(Collectors.toSet());
        }

        public String getName() {
            return name;
        }

        @Override
        public boolean equals(Object obj) {
            return obj != null && obj instanceof Save && ((Save)obj).name.equals(this.name);
        }
    }

    public static class SaveAlreadyExistsException extends UnknownSaveException {
        public SaveAlreadyExistsException() {
            super("save already exists");
        }
    }

    public static class UnknownSaveException extends Exception {
        private static final String DFLT_MSG = "An unknown error occured";

        public UnknownSaveException() {
            super(DFLT_MSG);
        }

        public UnknownSaveException(String message) {
            super(message);
        }

        public UnknownSaveException(String message, Throwable cause) {
            super(message, cause);
        }

        public UnknownSaveException(Throwable cause) {
            super(DFLT_MSG, cause);
        }
    }
}

圆.java

public class Circle implements Cloneable, Serializable {
    private static long nextID = 0;
    private float radius, centerX, centerY;
    private final long id;

    public Circle(float centerX, float centerY) {
        this(centerX, centerY, nextID++);
    }

    private Circle(float centerX, float centerY, long id) {
        this.radius = 0;
        this.centerX = centerX;
        this.centerY = centerY;
        this.id = id;
    }

    public float getRadius() {
        return radius;
    }

    public void setRadius(float radius) {
        this.radius = radius;
    }

    public float getCenterX() {
        return centerX;
    }

    public void setCenterX(float centerX) {
        this.centerX = centerX;
    }

    public float getCenterY() {
        return centerY;
    }

    public void setCenterY(float centerY) {
        this.centerY = centerY;
    }

    @Override public Circle clone() {
        return new Circle(getCenterX(), getCenterY(), id);
    }

    public boolean isCloneOf(Circle circle) {
        return circle != null && circle != this && this.id == circle.id;
    }

    @Override
    public boolean equals(Object obj) {
        return obj != null && obj instanceof Circle && !isCloneOf((Circle)obj);
    }
}

堆栈跟踪

E/java.io.NotSerializableException: java.io.NotSerializableException: android.app.Application at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) at com.multimedia.tp3.model.files.DataFileManager.save(DataFileManager.java:77) at com.multimedia.tp3.model.files.DataFileManager.forceSave(DataFileManager.java:116) at com.multimedia.tp3.DrawSurface.save(DrawSurface.java:131) at com.multimedia.tp3.MainActivity.onActivityResult(MainActivity.java:95) at android.app.Activity.dispatchActivityResult(Activity.java:6996) at android.app.ActivityThread.deliverResults(ActivityThread.java:4069) at android.app.ActivityThread.handleSendResult(ActivityThread.java:4116) at android.app.ActivityThread.-wrap20(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1516) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:159) at android.app.ActivityThread.main(ActivityThread.java:6097) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

最佳答案

it's an inner class of DataFileManager

将其设为public static class,而不是public class。现在,您的序列化对正在序列化的 DataFileManager 感到窒息,因为每个 Circle 都有一个隐式引用返回到创建它的外部类实例。

关于java - 尝试将可序列化对象写入文件时出现 NotSerializedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47126677/

相关文章:

java - 重新加载由 getResourceAsStream 加载的资源

java.lang.NoClassDefFoundError : Maven projects 错误

android - AppCompatEditText 的默认背景是什么?

android - 如何在 Xamarin 上创建一个根据平台执行不同操作的函数?

django - 在 Django 中序列化一棵树

c# - Newtonsoft.Json 用下划线替换空格 C# to JSON Serialize

java - 使用 Jackson 序列化和反序列化任意值

java - 为什么 ExecutorService.submit(Runnable task) 返回 Future<?> 而不是 Future<Void>?

javascript - Android 上的 RN 可访问性 - TalkBack 读取 View 的顺序

java - 如何使用 Producer 将自定义对象发送到 Kafka Topic