Discord JDA Bot 在调用扩展 class 时抛出 NullPointerException

Discord JDA Bot throws NullPointerException when calling extended class

我目前正尝试在 JDA 中编写一个非常基本的 Discord 机器人程序,我刚刚在尝试将我的代码整齐地分成 Main Class、MessageHandler 时遇到了一个问题一个 CommandHandler 和一个 VoiceHandler class。

Main Class 将添加一个 EventListener 以在收到事件时调用 MessageHandler,然后如果在命令之前看到 bot 前缀则分支到 CommandHandler。

问题是它在尝试使用 new CommandHandler.handleCmd 调用 CommandHandler 时抛出 NullPointerException。错误消息说 "ERROR JDA - One of the EventListeners had an uncaught exception" 但如果我没记错的话,它应该只是分支到 CommandHandler class 的 handleCmd 函数。所以我不明白为什么它会产生错误。

如有任何帮助,我们将不胜感激!

这是我的主Class

import net.dv8tion.jda.api.AccountType;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.hooks.ListenerAdapter;

import javax.security.auth.login.LoginException;

public class Main extends ListenerAdapter {
    public static void main(String[] args) throws LoginException {
        JDABuilder builder = new JDABuilder(AccountType.BOT);
        String token = "somethingsomething";
        builder.setToken(token);
        builder.addEventListeners(new MessageHandler());   //Puts Eventlistener to trigger MessageHandler

        builder.build();
    }
}

哪个应该触发我的 MessageHandler

import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;

public class MessageHandler extends ListenerAdapter {
    protected String userName;
    protected String userMessage;
    protected MessageReceivedEvent event;

    public void onMessageReceived(MessageReceivedEvent event) {
        userName = event.getAuthor().getName();
        userMessage = event.getMessage().getContentRaw();
        this.event = event;

        if (event.getAuthor().isBot()) {
            return;
        } else if (userMessage.startsWith(">")) {
            new CommandHandler().handleCmd();                            //Should trigger CommandHandler (this is the problem)
        }
    }
}

然后分支到CommandHandler

public class CommandHandler extends MessageHandler {
    private String command = userMessage.substring(1);

    public void handleCmd() {
        switch (command) {
            case "join":
                new VoiceHandler().join();
                break;
            case ... :
                ...
                break;
            case ... :
                ...
                break;
        }
    }
}

VoiceHandler.join() 方法只是让机器人连接到我的语音通道,但现在应该无关紧要

这里还有完整的错误信息,如果有帮助的话

[JDA MainWS-ReadThread] ERROR JDA - One of the EventListeners had an uncaught exception
java.lang.NullPointerException
    at CommandHandler.<init>(CommandHandler.java:2)
    at MessageHandler.onMessageReceived(MessageHandler.java:17)
    at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:376)
    at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
    at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:64)
    at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:151)
    at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:122)
    at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:853)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:741)
    at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:720)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:891)
    at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
    at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
    at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
    at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
    at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
    at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
    at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)

堆栈跟踪告诉您异常发生在哪一行(CommandHandler 的第 2 行)。

您的字段 userMessagenull 并且您正在对其执行方法调用。如果尚未在您的 CommandHandler 中设置 userMessage,就会发生这种情况。

下面一段代码

userMessage = event.getMessage().getContentRaw(); 

仅在当前 MessageHandler 对象中设置 userMessage。这些值不与新创建的 CommandHandler 对象共享。您需要使用构造函数或使用方法参数显式设置它们。您也可以将这些字段更改为静态字段。

使用构造函数的外观:

public class CommandHandler extends MessageHandler {
    private String command;

    /**
    *   You can add more parameters to this constructor or also a MessageHandler object.
    **/
    public CommandHandler(String userMessage){
        if(userMessage != null){
            this.comand = userMessage.substring(1);
        }
    }

    public void handleCmd() {
        switch (command) {
            case "join":
                new VoiceHandler().join();
                break;
            case ... :
                ...
                break;
            case ... :
                ...
                break;
        }
    }
}

对象创建如下所示:

if (event.getAuthor().isBot()) {
    return;
} else if (userMessage.startsWith(">")) {
    new CommandHandler(userMessage).handleCmd();
}

问题是为什么需要扩展MessageHandler?您正在像使用实用程序 class 一样使用它,因此我建议将其更改为实用程序 class:

public final class CommandHandler {

    public static void handleCmd(String userMessage) {
        if(userMessage == null){
            return;
        }
        String command = userMessage.substring(1);

        switch (command) {
            case "join":
                new VoiceHandler().join();
                break;
            case ... :
                ...
                break;
            case ... :
                ...
                break;
        }
    }
}

以及该方法的调用:

CommandHandler.handleCmd(userMessage);