第三方图形库中的 NotSerializableException
NotSerializableException in Third-Party Graphics Library
我使用 ACM 图形库 创建了 Atari Breakout 游戏的克隆,并且刚刚添加了高分界面和功能。玩家的名字和分数应该显示在 GUI 上 window(成功)并且也被写入 .dat
二进制文件。
但是,当代码尝试加载现有文件时,出现以下错误。
writing aborted; java.io.NotSerializableException: acm.graphics.GCanvasListener
我在网上研究了这个错误,看来可以通过编辑class来实现Serializable
来解决。但是,class 抛出此错误的 不是我自己的 而是属于第三方 ACM 图形库的 class 。我该如何解决这个问题?
我什至不确定为什么首先会导致此错误,因为我尝试序列化的数据 只是一个名称和 score,我'我没有尝试序列化 canvas 个对象或类似的东西。
主要class(称为突破)
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;
}
得分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; }
}
分数比较器class
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
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;
}
}
运行申请后:
[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
您应该转到 class 字段 name 和 score 所在的位置,然后添加例如 public class nameclass implements Serializable
.希望对你有用。
您的任务是找到从您的姓名和分数结构到 UI 组件的隐藏引用。许多 GUI 应用程序使用大量内部 classes,这可能是缺少的 link.
当你有一个 class 这样的东西时:
class MyGame {
private SomeUIWidget widget;
class TopScore implements Serializable {
String name;
int score;
...
}
...
}
TopScore
中有一个隐藏成员引用了 MyGame
的 "enclosing instance",包括它的 SomeUIWidget
成员。当您尝试序列化一个 TopScore
实例时,所有其余实例都会被拖入其中。
您可以简单地将 TopScore
声明为 static
嵌套 class。这意味着没有封闭实例,仅用于隐藏其他代码中的 TopScore
class。但是,我建议只在其自己的文件中将 TopScore
设为顶级 class,因为其他对象可能希望以不同的方式使用这些对象——也就是说,它看起来像一个public API.
的一部分的可能候选人
这是有根据的猜测,没有任何实际代码。要获得更好的答案,请将您的代码减少到演示问题所需的最低限度,并将其包含在您的问题中。
我使用 ACM 图形库 创建了 Atari Breakout 游戏的克隆,并且刚刚添加了高分界面和功能。玩家的名字和分数应该显示在 GUI 上 window(成功)并且也被写入 .dat
二进制文件。
但是,当代码尝试加载现有文件时,出现以下错误。
writing aborted; java.io.NotSerializableException: acm.graphics.GCanvasListener
我在网上研究了这个错误,看来可以通过编辑class来实现Serializable
来解决。但是,class 抛出此错误的 不是我自己的 而是属于第三方 ACM 图形库的 class 。我该如何解决这个问题?
我什至不确定为什么首先会导致此错误,因为我尝试序列化的数据 只是一个名称和 score,我'我没有尝试序列化 canvas 个对象或类似的东西。
主要class(称为突破)
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;
}
得分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; }
}
分数比较器class
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
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;
}
}
运行申请后:
[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
您应该转到 class 字段 name 和 score 所在的位置,然后添加例如 public class nameclass implements Serializable
.希望对你有用。
您的任务是找到从您的姓名和分数结构到 UI 组件的隐藏引用。许多 GUI 应用程序使用大量内部 classes,这可能是缺少的 link.
当你有一个 class 这样的东西时:
class MyGame {
private SomeUIWidget widget;
class TopScore implements Serializable {
String name;
int score;
...
}
...
}
TopScore
中有一个隐藏成员引用了 MyGame
的 "enclosing instance",包括它的 SomeUIWidget
成员。当您尝试序列化一个 TopScore
实例时,所有其余实例都会被拖入其中。
您可以简单地将 TopScore
声明为 static
嵌套 class。这意味着没有封闭实例,仅用于隐藏其他代码中的 TopScore
class。但是,我建议只在其自己的文件中将 TopScore
设为顶级 class,因为其他对象可能希望以不同的方式使用这些对象——也就是说,它看起来像一个public API.
这是有根据的猜测,没有任何实际代码。要获得更好的答案,请将您的代码减少到演示问题所需的最低限度,并将其包含在您的问题中。