Java - 指已实现的类

3
我有一个小问题:我为我的游戏开发了一个名为"ExampleQuest"的类,它扩展了抽象类Quest。我这样做是为了创建个别任务类。现在,我的ExampleQuest类应该计算我的实体死亡次数,所以我实现了我的EntityListener。现在,我必须在我的Playstate类中注册它,以使一切正常工作,但这里是我的实际问题:方法Playstate.addEntityListener(this)给了我一个nullpointer异常。我发现这个错误是由于任何扩展类引起的。如果ExampleQuest不扩展Quest,则一切正常工作。我的Quest类没有任何错误,因为如果我用其他东西扩展ExampleQuest,我也会得到nullpointer异常。
---> 所以我的解释是,Playstate.addEntityListener(this)中的this指的是在这种情况下扩展类Quest,而不是EntityListener。我如何解决我的问题?
public class ExampleQuest extends Quest implements EntityListener {

    public ExampleQuest() {
        super();
        Playstate.addEntityListener(this); //gives me nullointer exception 
    }

    //implemented method
    public void entityDeathEvent(EntityEvent e) {

    }
}

This is a part of my Playstate class:

public class Playstate {

    public static Set<EntityListener> entityListener;

    public Playstate() {
        entityListener = new HashSet<EntityListener>();
    }

    public static void addEntityListener(EntityListener listener) {
        entityListener.add(listener);
    }
}

编辑:这个功能正常运作:

public class EventHandler implements EntityListener {

    public EventHandler() {
        Playstate.addEntityListener(this);
    }
}

它之所以有效,是因为EventHandler仅实现了一个类。


1
展示Qwest类。至少包括字段和构造函数。 - Sean Bright
你能发布堆栈跟踪吗? - Jan
1
目前还没有创建Playstate实例,因此静态字段尚未从未调用的Playstate构造函数中分配。使用静态是可疑的,但可以通过在声明中赋值(例如public static Set<EntityListener> entityListener = new HashSet<EntityListener>();)或静态初始化块(然后从Playstate构造函数中删除赋值)来“修复”。 - user2864740
3个回答

1
你的字段 entityListener 为空,因为它是静态的,只有在创建 Playstate 对象时才初始化该字段。
很可能,既不应该将 entityListener 设为静态,也不应该将 addEntityListener 设为静态。 将它们设为实例成员即可。
public class Playstate {

    public Set<EntityListener> entityListener;

    public Playstate() {
        entityListener = new HashSet<EntityListener>();
    }

    public void addEntityListener(EntityListener listener) {
        entityListener.add(listener);
    }
}

关于您的编辑:我们只能假设当您的EventHandler代码运行时,它能够正常工作,因为您已经在代码的其他地方创建了一个Playstate对象。
对于Playstate使用静态事件监听器意味着所有这样的对象将共享事件监听器,这是一个糟糕的想法。实际上,将它们设置为实例成员会更好。

如果我像这样创建一个类:public class EventHandler implements EntityListener {public EventHandler() { Playstate.addEntityListener(this); } }一切都正常工作,因为该类只是实现而不是扩展。 - AvarionDE

1
您出现NPE的原因是entityListener未初始化。 entityListener未初始化的原因是在使用addEntityListener方法之前,您的代码需要创建Playstate实例,但是您在创建Playstate实例之前调用了addEntityListener
这是错误的:静态变量不应在实例构造函数中初始化。 您需要在声明中执行此操作,就像这样
public static Set<EntityListener> entityListener = new HashSet<EntityListener>();

或者在static初始化块中,像这样:
public static Set<EntityListener> entityListener;

static {
    entityListener = new HashSet<EntityListener>();
}

entityListener变成实例变量也可以,但你需要提供一种方法来从ExampleQuest构造函数的上下文中获取一个Playstate实例。

谢谢你的帮助:)这对我来说相当困惑,我正在自学Java,直到现在我才知道static { }。 - AvarionDE

0
public Playstate() {
    entityListener = new HashSet<EntityListener>();
}

public static void addEntityListener(EntityListener listener) {
    entityListener.add(listener);
}

当PlayState构造函数被构建时,entityListener静态变量被赋值。这是一个严重的设计问题:要么监听器是静态的,因此不与任何PlayState实例相关联,因此不应在每次创建实例时分配它,要么它与给定实例相关联,因此不应该是静态的。

监听器和addEntityListener()方法不应该是静态的。相反,Quests应该引用PlayState类的实例。

此外,由于它是一组侦听器,因此变量应命名为entityListeners,而不是entityListener。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接