Discord JDA Bot 在调用扩展类时抛出 NullPointerException
Posted
技术标签:
【中文标题】Discord JDA Bot 在调用扩展类时抛出 NullPointerException【英文标题】:Discord JDA Bot throws NullPointerException when calling extended class 【发布时间】:2020-05-11 05:53:29 【问题描述】:我目前正在尝试在 JDA 中编写一个非常基本的 Discord 机器人,但我在尝试将我的代码巧妙地分成一个主类、MessageHandler
、CommandHandler
和 @987654323 时遇到了一个问题@ 班级。
如果收到事件,主类将添加一个 EventListener 来调用 MessageHandler,如果在命令之前看到机器人前缀,则分支到 CommandHandler。
问题是当它尝试使用new CommandHandler.handleCmd
调用CommandHandler 时会抛出NullPointerException。错误消息说"ERROR JDA - One of the EventListeners had an uncaught exception"
但如果我没记错的话,它应该只是分支到 CommandHandler 类的 handleCmd 函数。所以我不明白为什么它会产生错误。
任何帮助将不胜感激!
这是我的主要课程
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)
【问题讨论】:
【参考方案1】:堆栈跟踪告诉您异常发生在哪一行(CommandHandler
的第 2 行)。
您的字段userMessage
是null
,您正在对其执行方法调用。如果您的 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?您正在像使用实用程序类一样使用它,因此我建议将其更改为实用程序类:
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);
【讨论】:
嘿,谢谢你的提示!我已经尝试过您的修复并设法将问题本地化。当handleCmd()
被调用时,Message Handler
的所有属性由于某种原因被设置为空,但我似乎无法使用super.attribute
或类似方法重新声明它们。您是否对如何坚持 userMessage
、event
和 userName
进入 CommandHandler
课程有一些建议?我正在考虑将它作为参数提供给handleCmd
方法,但我不知道这是否会很快变得相当丑陋。
抱歉,我没有仔细阅读您的示例。我修正了我的答案。
现在可以完美运行了!我松了一口气,我可以保持我最初想要的代码结构。感谢您的帮助!以上是关于Discord JDA Bot 在调用扩展类时抛出 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章
Java Discord Bot (JDA) 检查是不是固定
Discord bot 无法使用 JDA 在 java 中发送消息
如何获取 Bot 消息 ID 并编辑消息 - Discord JDA Java