【问题标题】:How do I pass instances of the main class to multiple listeners?如何将主类的实例传递给多个侦听器?
【发布时间】:2014-05-07 22:32:20
【问题描述】:

所以,我一直在开发一个插件。一切都很顺利,直到我偶然发现了一个问题。我正在使用单独的 Listener (implements Listener) 类来管理我的事件,但对于其中一些,我需要访问 JavaPlugin 方法,例如获取配置文件。

在我的侦听器类中使用构造函数 below 有效,但如果我尝试在另一个类中使用相同的东西,Eclipse 会给它一个可爱的红色下划线,表示 blank final field plugin may have not been initialized

private final MainClass plugin;
public ListenerClass(MainClass instance){
    this.plugin = instance;
}

如前所述,上述代码有效,但仅适用于一位听众。 below 的构造函数在使用返回对象的方法时会抛出 NPE。我不知道这是因为插件实例实际上返回为null,或者如果没有句柄if它是null。

// The only difference between this constructor and the last is that the final
// modifier was removed.
private MainClass plugin;
public ListenerClass(MainClass instance){
    this.plugin = instance;
}

FileConfiguration config = plugin.getConfig(); // throws NPE
// Let's pretend that the line above isn't there, and I just use the getConfig() method instead.

@EventHandler
public void onJoin(PlayerJoinEvent event){
    if(plugin.getConfig().getString("Strings.cat-toy").toLowerCase().equals("string")){ // throws NPE
        // do stuff
    }
}

【问题讨论】:

    标签: java listener bukkit


    【解决方案1】:

    我做的事情与大多数人不同。假设您的班级 extends JavaPlugin 是 Main.java,您将在任何方法中添加以下代码:

    public static Main plugin;
    

    然后将其添加到您的onEnable():

    plugin = this
    

    所以,您的 Main 类可能看起来像这样。

    public class Main extends JavaPlugin{
      public static Main plugin; //create the variable
    
      @Override
      public void onEnable(){
        plugin = this; //assign plugin to this class
        //other onEnable things
      }
    
      @Override
      public void onDisable(){
        //onDisable things
        plugin = null; //best to put this AFTER running any methods here
      }
    }
    

    然后,在任何要使用JavaPlugin 方法的类中,只需使用Main.plugin

    所以,如果你想在另一个类中为你的插件获取配置,你可以这样做:

    YamlConfiguration config = Main.plugin.getConfig();
    

    只需确保在将 plugin 分配给主文件之后执行此操作。假设Handler.setup() 在其中使用YamlConfiguration config = Main.plugin.getConfig();,并且您希望在启用插件时运行该方法。你可以这样做:

    public void onEnable(){
      plugin = this;
      Handler.setup();
    }
    

    但是不是这个:

    public void onEnable(){
      Handler.setup();
      plugin = this;
    }
    

    【讨论】:

    • 是的。我搞砸了,我意识到Plugin 对象继承了与JavaPlugin 对象相同的方法。我做了一些与此非常相似的事情并且它有效。非常感谢!我已经被这个问题困扰了一两个月了。请务必在 onDisable() 方法中将 plugin 设置为 null 以防止内存泄漏!
    【解决方案2】:

    你必须重新发明Singleton Pattern。

    public class MainClass extends JavaPlugin {
        private static MainClass instance;
        public MainClass() {
            instance = this;
        }
        public static MainClass getInstance() {
            return instance;
        }
        @Override
        public void onEnable() {
            Listener listener = new ListenerClass();
        }
    }
    

    您现在可以直接访问实例,而无需在 ListenerClass 中创建成员变量。

    public class ListenerClass implements Listener {
        public ListenerClass() {
            Plugin main = MainClass.getInstance();
            main.getServer().getPluginManager().registerEvents(this, main);
        }
    }
    

    【讨论】:

    • 不能放在构造函数中,需要在onEnable中,这就是onEnable的作用。插件加载器在 JavaPlugin 类中有 3 个不同的构造函数,所以你不能只把它放在那个里面。
    • @gogobebe2 将其设为非公开不会让插件加载,因此应始终调用它。
    • 我听不懂你在说什么?
    • @gogobebe2 如果您声明一个私有的空构造函数,您的插件将不会加载。这就是为什么我认为它总是会被调用。
    • 是的,你可能是对的。但是在主类的 spigot 中使用构造函数被认为是不好的。也许它不受欢迎是有原因的。您之前是否在构造函数中测试过使用它?另外,有一个 onEnable() 方法是有原因的,我认为最好使用它,以防服务器重新加载等引起的错误。
    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 2019-03-29
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2013-12-18
    • 2014-02-15
    • 2010-09-20
    相关资源
    最近更新 更多