所以我正在修改一个现有的开源项目,我创建了一个新的监视器类,我用它来使用观察者模式观察现有类的变化,它本身正在被更多的监视器类监视。
在原始系统的主类中,我已经让它工作了,但是当程序切换到其他类时,我尝试通过新类的构造函数传递管理器(通过包含程序更新监视器的 send() 函数的接口(interface) Manager 表示)。但是,当我尝试从其他类调用 send 时,它不起作用(它在第一个类中,称为 Main)。
当我在这个新类中声明的“MouseHandler”类中调用 send() 时,出现以下错误:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at kabalpackage.GameArea$MouseHandler.mouseReleased(GameArea.java:565)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
我尝试在此 MouseHandler 类中声明另一个 Manager 变量,并将其传递到构造函数中,但遇到了相同的错误。
这是它工作的类,但为了简单起见,我省略了很多代码。
/*added necessary imports */
import java.util.*;
import monitors.Manager;
import monitors.MonManager;
public class Main
extends JFrame
{
// added manager variable
public static Manager manager;
public Main(Manager m)
{
// this is where I set the manager provided in the constructor
this.manager = m;
// ..... lots of code skipped
// I try and pass the manager in to the new class here
private GameArea gameArea = new GameArea(manager);
private class MenuBar
extends JMenuBar
{
//.....lots of code skipped
}
private class MenuListener
implements ActionListener
{
private MenuListener() {}
public void actionPerformed(ActionEvent e)
{
String event = e.getActionCommand();
if (event.equals("New Game"))
{
// here is where i call send on the monitor
System.out.println("Sending win 0");
manager.send("win 0");
Main.this.gameArea.newGame();
System.out.println("New game");
}
}
}
}
}
}
如您所见,在类中声明了一个新类。这是从上面的类调用的类 GameArea,您可以看到我修改了构造函数以采用管理器(接口(interface))对象,因此我可以将相同的监视器管理器传递到下一个类中。我再次从此类中省略了很多代码,包括一些导入(它仍然具有 import java.util.*;我认为发送事件需要它)。
import monitors.MonManager;
import monitors.Manager;
public class GameArea
extends JPanel
{
public static Manager manager;
// loads of variables omitted //
// heres the constructor for the class, a manager is passed in and set to variable Manager
public GameArea(Manager m)
{
setLayout(null);
setBackground(this.BACKGROUND_COLOR);
setCursor(new Cursor(12));
this.manager = m;
loadImages();
}
// more code omitted //
public void newGame()
{
removeAll();
// this creates the mouse handler class where i try to call manager.send
MouseHandler mh = new MouseHandler();
}
// more code omitted //
public class MouseHandler
extends MouseInputAdapter
{
// variables omitted
private MouseHandler() {
}
public void mouseMoved(MouseEvent e)
{
//
}
public void mousePressed(MouseEvent e)
{
// omitted code //
}
public void mouseDragged(MouseEvent e)
{
// omitted code //
}
public void mouseClicked(MouseEvent e)
{
// omitted code
}
public void mouseReleased(MouseEvent e)
{
// more omitted code
if ((this.SRC_STACK instanceof DealtCardsStack)) {
GameArea.this.moves.clear();
// a call of manager
System.out.println("Sending moves");
manager.send("moves");
} else {
GameArea.this.moves.add(new Move(this.SRC_STACK, this.DST_STACK, this.TMP_LIST));
// Here is the call for the manager, which creates an error.
System.out.println("Sending moves");
manager.send("moves");
}
}
else
{
this.SRC_STACK.showCards(this.TMP_LIST);
}
// skipped some code//
}
}
最后这是我的管理器界面中由监视器管理器实现的代码:
package monitors;
public interface Manager {
public void send(String message);
}
抱歉,如果问题不清楚。有很多代码需要省略,所以看起来很困惑,但我不认为我遗漏的任何内容都会对错误产生影响。所以基本上在主类中我的消息被发送到监视器实现管理器,但在另一个类中它们不是,我不知道为什么。
非常感谢所有耐心阅读本文的人,特别感谢您能告诉我我的问题是什么!
最佳答案
字段初始化是在实际构造函数执行之前完成的,因此该行
private GameArea gameArea = new GameArea(manager);
正在传递一个未初始化的管理器,从而导致 NullPointerException。
只需将初始化放入构造函数中,如 gameArea = new GameArea(manager);
即可解决问题。
关于java - Java中实现观察者模式,同一个观察者跨多个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20079262/