当我尝试为 Space Invaders 克隆加载游戏时出现 ClassCastException
ClassCastException when I try to load gameplay for Space Invaders clone
编辑:由 Mark Rotteveel 解决!在保存期间,我使用的是 oos.writeObject(this);
而不是 oos.writeObject(GamePlay.this);
所以我在加载函数工作时遇到了很多麻烦。当我将此逻辑应用于简单程序时,我从未遇到过问题,这是我第一次制作涉及序列化和线程的东西。所以我有预感问题是由于线程引起的。
所以我做这个的方法是我有一个游戏 class 可以使用它来保存自己。保存此文件没有错误,它成功出现在我的文件夹中。:
try {
FileOutputStream fos = new FileOutputStream("C:\temp\gameplay.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(this);
}
System.out.println("Gameplay Saved");
} catch (IOException e) {
System.out.println("Error Saving");
}
当我玩游戏的时候,控制台提示我保存成功。但是,当我重新启动游戏并尝试加载它时,我得到了 ClassCastException。这是加载游戏代码
public void actionPerformed(ActionEvent arg0) {
try {
FileInputStream fi = new FileInputStream("C:\temp\gameplay.dat");
ObjectInputStream oi = new ObjectInputStream(fi);
try {
Gameplay game = new Gameplay();
try {
game = (Gameplay) oi.readObject();
} catch (ClassCastException e) {
System.out.println("ClassCastException ");
}
oi.close();
fi.close();
game.addKeyBindings(panelCont);
frame.add(game);
Thread t1 = new Thread(game);
t1.start();
} catch (ClassNotFoundException ex) {
Logger.getLogger(SpaceRaiders.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException e) {
System.out.println("File not found");
} catch (IOException e) {
System.out.println("Error initializing stream");
}
我真的很想了解发生了什么,如果有人能简单地指出我正确的方向,我将不胜感激!
请注意,如果您需要查看游戏玩法class,我不介意发布它,但它很长,我不想让人不知所措。
这是游戏玩法class
public class Gameplay extends JPanel implements ActionListener, Runnable, Serializable {
private Ship player = new Ship(new Point(200, 555));
private Timer t = new Timer(5, this);
private int score;
//Laser and shot variables ----------
private ArrayList<Laser> lasers = new ArrayList<Laser>();
private boolean readytofire;
private boolean shot = false;
//Invader variables -----------
private ArrayList<Invader> invaders = new ArrayList<Invader>();
public Gameplay() {
super();
t.start();
setFocusable(true);
requestFocus();
setFocusTraversalKeysEnabled(false);
for (int j = 0; j < 80; j += 20) {
for (int i = 0; i < 20; i++) {
invaders.add(new Invader(5 + i * 30, j));
}
}
}
public boolean addLaser(Laser a) {
lasers.add(a);
return true;
}
public boolean addPlayer(Ship p) {
this.player = p;
return true;
}
// Les évenements claviers --------------------
@Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
public void addKeyBindings(JComponent jc) {
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "moveRight");
jc.getActionMap().put("moveRight", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
moveRight();
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "moveLeft");
jc.getActionMap().put("moveLeft", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
moveLeft();
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "shoot");
jc.getActionMap().put("shoot", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
shoot();
}
});
// FONCTIONS DE SAUVEGARDE------------------------
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "save");
jc.getActionMap().put("save", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
try {
FileOutputStream fos = new FileOutputStream("C:\temp\gameplay.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(this);
}
System.out.println("Gameplay Saved");
} catch (IOException e) {
System.out.println("Error Saving");
}
}
});
}
// Le mouvement du Ship --------------------
public void moveRight() {
if (player.getCentre().getX() >= 580) {
player.setX(580);
} else {
double movement = player.getCentre().getX();
movement += 10;
player.setX(movement);
}
this.repaint();
}
public void moveLeft() {
if (player.getCentre().getX() <= 20) {
player.setX(20);
} else {
double movement = player.getCentre().getX();
movement -= 10;
player.setX(movement);
}
this.repaint();
}
// Création du laser --------------------
public void shoot() {
shot = true;
if (readytofire) {
Point top = new Point(player.getTopX(), player.getTopY());
Laser laser = new Laser(top);
addLaser(laser);
}
}
// Mouvement du laser --------------------
public void moveShot() {
if (shot) {
for (Laser l : lasers) {
l.setY(l.getTopLeft().getY() - 2);
}
}
}
// Collision Detection
public boolean checkCollision(Invader i, Laser l) {
double x = i.getlocX();
double y = i.getlocY();
if (l.getX() > x && l.getX() < x + 15 && l.getY() > y && l.getY() < y + 15) {
return true;
} else {
return false;
}
}
public boolean outBounds(Laser l) {
if (l.getY() == 0) {
return true;
} else {
return false;
}
}
// Dessiner les graphiques --------------------
@Override
public void paint(Graphics g) {
setBackground(Color.black);
super.paint(g);
player.draw(g);
try {
for (Laser l : lasers) {
l.draw(g);
}
for (Invader i : invaders) {
i.draw(g);
}
} catch (Exception e) {
}
g.drawString("Score: " + score, 0, 10);
}
// public void paintComponent (Graphics g){
// Controle Thread
public void run() {
while (true) {
moveShot();
//Verifie Collision-------------------------------------------------
List<Invader> invaderRemove = new ArrayList<Invader>();
List<Laser> laserRemove = new ArrayList<Laser>();
for (Invader i : invaders) {
for (Laser l : lasers) {
if (checkCollision(i, l) == true) {
laserRemove.add(l);
invaderRemove.add(i);
score += 1;
}
}
}
lasers.removeAll(laserRemove);
invaders.removeAll(invaderRemove);
//Enleve les lasers si ils arrivent a la fin du frame---------------
for (Laser l : lasers) {
if (outBounds(l) == true) {
laserRemove.add(l);
}
}
lasers.removeAll(laserRemove);
//Mouvement des invaders
for (Invader i : invaders) {
i.moveAndUpdate();
}
try {
Thread.sleep(10);
readytofire = true;
} catch (InterruptedException ex) {
Logger.getLogger(Gameplay.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
和堆栈跟踪
java.lang.ClassCastException: spaceraiders.vue.Gameplay cannot be cast to spaceraiders.vue.Gameplay
at spaceraiders.Controlleur.SpaceRaiders.actionPerformed(SpaceRaiders.java:106)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue.run(EventQueue.java:731)
at java.awt.EventQueue.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
这是您的代码:
jc.getActionMap().put("save", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
try {
FileOutputStream fos = new FileOutputStream("C:\temp\gameplay.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(this);
}
System.out.println("Gameplay Saved");
} catch (IOException e) {
System.out.println("Error Saving");
}
}
});
这将创建一个匿名 class,oos.writeObject(this)
中的 this
引用此匿名 class。它不涉及您的 GamePlay
实例。因此,您正在序列化 Action
,当反序列化并强制转换为 GamePlay
时,强制转换失败。
您需要使操作调用 GamePlay
class 中包含实际序列化代码的方法,或者您需要使用 [=17] 引用封闭的 class =].详情见:Getting hold of the outer class object from the inner class object
编辑:由 Mark Rotteveel 解决!在保存期间,我使用的是 oos.writeObject(this);
而不是 oos.writeObject(GamePlay.this);
所以我在加载函数工作时遇到了很多麻烦。当我将此逻辑应用于简单程序时,我从未遇到过问题,这是我第一次制作涉及序列化和线程的东西。所以我有预感问题是由于线程引起的。
所以我做这个的方法是我有一个游戏 class 可以使用它来保存自己。保存此文件没有错误,它成功出现在我的文件夹中。:
try {
FileOutputStream fos = new FileOutputStream("C:\temp\gameplay.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(this);
}
System.out.println("Gameplay Saved");
} catch (IOException e) {
System.out.println("Error Saving");
}
当我玩游戏的时候,控制台提示我保存成功。但是,当我重新启动游戏并尝试加载它时,我得到了 ClassCastException。这是加载游戏代码
public void actionPerformed(ActionEvent arg0) {
try {
FileInputStream fi = new FileInputStream("C:\temp\gameplay.dat");
ObjectInputStream oi = new ObjectInputStream(fi);
try {
Gameplay game = new Gameplay();
try {
game = (Gameplay) oi.readObject();
} catch (ClassCastException e) {
System.out.println("ClassCastException ");
}
oi.close();
fi.close();
game.addKeyBindings(panelCont);
frame.add(game);
Thread t1 = new Thread(game);
t1.start();
} catch (ClassNotFoundException ex) {
Logger.getLogger(SpaceRaiders.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException e) {
System.out.println("File not found");
} catch (IOException e) {
System.out.println("Error initializing stream");
}
我真的很想了解发生了什么,如果有人能简单地指出我正确的方向,我将不胜感激!
请注意,如果您需要查看游戏玩法class,我不介意发布它,但它很长,我不想让人不知所措。
这是游戏玩法class
public class Gameplay extends JPanel implements ActionListener, Runnable, Serializable {
private Ship player = new Ship(new Point(200, 555));
private Timer t = new Timer(5, this);
private int score;
//Laser and shot variables ----------
private ArrayList<Laser> lasers = new ArrayList<Laser>();
private boolean readytofire;
private boolean shot = false;
//Invader variables -----------
private ArrayList<Invader> invaders = new ArrayList<Invader>();
public Gameplay() {
super();
t.start();
setFocusable(true);
requestFocus();
setFocusTraversalKeysEnabled(false);
for (int j = 0; j < 80; j += 20) {
for (int i = 0; i < 20; i++) {
invaders.add(new Invader(5 + i * 30, j));
}
}
}
public boolean addLaser(Laser a) {
lasers.add(a);
return true;
}
public boolean addPlayer(Ship p) {
this.player = p;
return true;
}
// Les évenements claviers --------------------
@Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
public void addKeyBindings(JComponent jc) {
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "moveRight");
jc.getActionMap().put("moveRight", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
moveRight();
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "moveLeft");
jc.getActionMap().put("moveLeft", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
moveLeft();
}
});
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "shoot");
jc.getActionMap().put("shoot", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
shoot();
}
});
// FONCTIONS DE SAUVEGARDE------------------------
jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "save");
jc.getActionMap().put("save", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
try {
FileOutputStream fos = new FileOutputStream("C:\temp\gameplay.dat");
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(this);
}
System.out.println("Gameplay Saved");
} catch (IOException e) {
System.out.println("Error Saving");
}
}
});
}
// Le mouvement du Ship --------------------
public void moveRight() {
if (player.getCentre().getX() >= 580) {
player.setX(580);
} else {
double movement = player.getCentre().getX();
movement += 10;
player.setX(movement);
}
this.repaint();
}
public void moveLeft() {
if (player.getCentre().getX() <= 20) {
player.setX(20);
} else {
double movement = player.getCentre().getX();
movement -= 10;
player.setX(movement);
}
this.repaint();
}
// Création du laser --------------------
public void shoot() {
shot = true;
if (readytofire) {
Point top = new Point(player.getTopX(), player.getTopY());
Laser laser = new Laser(top);
addLaser(laser);
}
}
// Mouvement du laser --------------------
public void moveShot() {
if (shot) {
for (Laser l : lasers) {
l.setY(l.getTopLeft().getY() - 2);
}
}
}
// Collision Detection
public boolean checkCollision(Invader i, Laser l) {
double x = i.getlocX();
double y = i.getlocY();
if (l.getX() > x && l.getX() < x + 15 && l.getY() > y && l.getY() < y + 15) {
return true;
} else {
return false;
}
}
public boolean outBounds(Laser l) {
if (l.getY() == 0) {
return true;
} else {
return false;
}
}
// Dessiner les graphiques --------------------
@Override
public void paint(Graphics g) {
setBackground(Color.black);
super.paint(g);
player.draw(g);
try {
for (Laser l : lasers) {
l.draw(g);
}
for (Invader i : invaders) {
i.draw(g);
}
} catch (Exception e) {
}
g.drawString("Score: " + score, 0, 10);
}
// public void paintComponent (Graphics g){
// Controle Thread
public void run() {
while (true) {
moveShot();
//Verifie Collision-------------------------------------------------
List<Invader> invaderRemove = new ArrayList<Invader>();
List<Laser> laserRemove = new ArrayList<Laser>();
for (Invader i : invaders) {
for (Laser l : lasers) {
if (checkCollision(i, l) == true) {
laserRemove.add(l);
invaderRemove.add(i);
score += 1;
}
}
}
lasers.removeAll(laserRemove);
invaders.removeAll(invaderRemove);
//Enleve les lasers si ils arrivent a la fin du frame---------------
for (Laser l : lasers) {
if (outBounds(l) == true) {
laserRemove.add(l);
}
}
lasers.removeAll(laserRemove);
//Mouvement des invaders
for (Invader i : invaders) {
i.moveAndUpdate();
}
try {
Thread.sleep(10);
readytofire = true;
} catch (InterruptedException ex) {
Logger.getLogger(Gameplay.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
和堆栈跟踪
java.lang.ClassCastException: spaceraiders.vue.Gameplay cannot be cast to spaceraiders.vue.Gameplay
at spaceraiders.Controlleur.SpaceRaiders.actionPerformed(SpaceRaiders.java:106)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access0(EventQueue.java:97)
at java.awt.EventQueue.run(EventQueue.java:709)
at java.awt.EventQueue.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue.run(EventQueue.java:731)
at java.awt.EventQueue.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
这是您的代码:
jc.getActionMap().put("save", new AbstractAction() { @Override public void actionPerformed(ActionEvent ae) { try { FileOutputStream fos = new FileOutputStream("C:\temp\gameplay.dat"); try (ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(this); } System.out.println("Gameplay Saved"); } catch (IOException e) { System.out.println("Error Saving"); } } });
这将创建一个匿名 class,oos.writeObject(this)
中的 this
引用此匿名 class。它不涉及您的 GamePlay
实例。因此,您正在序列化 Action
,当反序列化并强制转换为 GamePlay
时,强制转换失败。
您需要使操作调用 GamePlay
class 中包含实际序列化代码的方法,或者您需要使用 [=17] 引用封闭的 class =].详情见:Getting hold of the outer class object from the inner class object