简体   繁体   English

第三方图形库中的NotSerializableException

[英]NotSerializableException in Third-Party Graphics Library

I have created a clone of Atari Breakout game using the ACM graphics library and just finished adding a highscore interface and functionality. 我使用ACM图形库创建了一个Atari Breakout游戏的克隆,刚刚完成了高分数界面和功能的添加。 The player's name and score should be displayed on the GUI window (it is successfully) and also be written to a .dat binary file. 玩家的名字和分数应该显示在GUI窗口上(成功),也可以写入.dat二进制文件。

However, when the code attempts to load the existing file I get the following error. 但是,当代码尝试加载现有文件时,我收到以下错误。

writing aborted; java.io.NotSerializableException: acm.graphics.GCanvasListener

I've researched this error online and it seems it can be solved by editing the class to implement Serializable . 我已经在线研究了这个错误,似乎可以通过编辑类来实现Serializable来解决它。 However, the class throwing this error is not one of my own but rather a class that belongs to the third-party ACM graphics library . 但是,抛出此错误的类不是我自己的错误而是属于第三方ACM图形库的类 How do I solve this? 我该如何解决这个问题?

I'm not even sure why this error is being caused in the first place since the data I'm attempting to serialize is only a name and scor e, I'm not trying to serialize a canvas of objects or anything like that. 我甚至不确定为什么这个错误在第一时间引起,因为我试图序列化的数据只是一个名称和scor e,我不是试图序列化对象的画布或类似的东西。

Main class (called Breakout) 主类(称为突破)

public class Breakout extends GraphicsProgram {
    ... // game variables
    public void run() {
        ... // this if clause runs when game ends
        if (brickCounter > 0) {
                removeAll(); // clears screen
                printGameOver(); // displays game over message
                HighscoreManager hm = new HighscoreManager();
                String name = getHighScoreName();
                hm.addScore(name, score);
                hm.displayHighscores();
        }
    }
    ... // game functionality methods
    private String getHighScoreName(){
        IODialog dialog = new IODialog();
        String name = dialog.readLine("Enter your name: ");
        return name;
    }

Score class 分数类

private class Score implements Serializable {
    private int score;
    private String name;

    public Score(String name, int score) {
        this.score = score;
        this.name = name;
    }

    public int getScore() { return score; }
    public String getName() { return name; }
}

ScoreComparator class ScoreComparator类

private class ScoreComparator implements Comparator<Score> {
    public int compare(Score score1, Score score2) {

        int sc1 = score1.getScore();
        int sc2 = score2.getScore();

        if (sc1 > sc2) {
            return -1;
        } else if (sc1 < sc2) {
            return 1;
        } else {
            return 0;
        }
    }
}

HighscoreManager class HighscoreManager类

private class HighscoreManager {
    private ArrayList<Score> scores;
    private static final String HIGHSCORE_FILE = ".//bin//scores.dat";
    ObjectOutputStream outputStream = null;
    ObjectInputStream inputStream = null;

    public HighscoreManager() {
        scores = new ArrayList<Score>(10);
    }

    public ArrayList<Score> getScores() {
        loadScoreFile();
        sort();
        return scores;
    }

    private void sort() {
        ScoreComparator comparator = new ScoreComparator();
        Collections.sort(scores, comparator);
    }

    public void addScore(String name, int score) {
        loadScoreFile();
        scores.add(new Score(name, score));
        updateScoreFile();
    }

    public void loadScoreFile() {
        try {
            inputStream = new ObjectInputStream(new FileInputStream(HIGHSCORE_FILE));
            scores = (ArrayList<Score>) inputStream.readObject();
        }
        catch (FileNotFoundException e) {
            System.out.println("[Load] File Not Found Error: " + e.getMessage());
        }
        catch (IOException e) {
            System.out.println("[Load] Input/Output Error: " + e.getMessage());
        }
        catch (ClassNotFoundException e) {
            throw new RuntimeException("[Load] Class Not Found Error: " + e.getMessage());
        }
        finally {
            try {
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
            } catch (IOException e) {
                System.out.println("[Load] Input/Output Error: " + e.getMessage());
            }
        }
    }

    public void updateScoreFile() {
        try {
            outputStream = new ObjectOutputStream(new FileOutputStream(HIGHSCORE_FILE));
            outputStream.writeObject(scores);
        }
        catch (FileNotFoundException e) {
            System.out.println("[Update] File Not Found Error: " + e.getMessage());
        }
        catch (IOException e) {
            System.out.println("[Update] Input/Output Error: " + e.getMessage());
        }
        finally {
            try {
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
            } catch (IOException e) {
                System.out.println("[Update] Input/Output Error: " + e.getMessage());
            }
        }
    }

    public void displayHighscores() {
        int max = 10;
        ArrayList<Score> scores;
        scores = getScores();
        int x = scores.size();

        if (x > max) {
            x = max;
        }

        removeAll(); // clears screen
        int npos = 160;
        int spos = 160;

        for (int i = 0; i < x; i++) {
            GLabel showName = new GLabel(scores.get(i).getName(), (getWidth() / 2.0) - 100, (getHeight() / 2.0) - npos);
            showName.move(-showName.getWidth() / 2, -showName.getHeight());
            showName.setColor(Color.WHITE);
            add(showName);
            npos -= 40;
        }

        for (int i = 0; i < x; i++) {
            GLabel showScore = new GLabel(Integer.toString(scores.get(i).getScore()), (getWidth() / 2.0) + 100, (getHeight() / 2.0) - spos);
            showScore.move(-showScore.getWidth() / 2, -showScore.getHeight());
            showScore.setColor(Color.WHITE);
            add(showScore);
            spos -= 40;
        }
    }

After running the application: 运行应用程序后:

[Load] Input/Output Error: writing aborted; java.io.NotSerializableException: acm.graphics.GCanvasListener
[Update] Input/Output Error: acm.graphics.GCanvasListener
[Load] Input/Output Error: writing aborted; java.io.NotSerializableException: acm.graphics.GCanvasListener

You should go to the class where the fields name and score are, and add for example public class nameclass implements Serializable . 您应该转到字段名称分数所在的类,并添加例如public class nameclass implements Serializable I hope it works for you. 我希望这个对你有用。

Your task will be to find a hidden reference from your name and score structure to the UI components. 您的任务是查找从您的名称和分数结构到UI组件的隐藏引用。 Many GUI applications use a lot of inner classes, and this might be the missing link. 许多GUI应用程序使用大量内部类,这可能是缺少的链接。

When you have a class something like this: 当你有一个像这样的课:

class MyGame {
    private SomeUIWidget widget;
    class TopScore implements Serializable {
        String name;
        int score;
        ...
    }
    ...
}

There is a hidden member in TopScore that references the "enclosing instance" of MyGame , including its SomeUIWidget member. 有一个隐藏的成员TopScore引用的“外围实例” MyGame ,包括其SomeUIWidget成员。 When you try to serialize a TopScore instance, all the rest gets dragged in with it. 当您尝试序列化TopScore实例时,其余所有内容都会被拖入。

You could simply declare TopScore as a static nested class. 您可以简单地将TopScore声明为static嵌套类。 This means that there is no enclosing instance, and serves only to hide the TopScore class from other code. 这意味着没有封闭实例,仅用于隐藏TopScore类与其他代码。 But, I would suggest just making TopScore a top-level class, in its own file, because it's likely that other objects will want to use those objects in different ways—that is, it seems like a likely candidate for part of your public API. 但是,我建议只在其自己的文件TopScore作为顶级类,因为其他对象可能希望以不同的方式使用这些对象 - 也就是说,它似乎可能是部分公共API的候选对象。

This is an educated guess, in the absence of any actual code. 在没有任何实际代码的情况下,这是一个有根据的猜测。 To get a better answer, reduce your code to the minimum required to demonstrate the problem, and include that in your question. 要获得更好的答案,请将代码降低到演示问题所需的最低限度,并将其包含在您的问题中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM