JDA API中ListenerAdapter实例内存地址异常?/info命令无响应排查
问题:JDA机器人/info命令无响应,handle方法未被调用
刚接触JDA API,尝试开发/info命令时遇到机器人无响应的问题,调试发现InfoCommand的handle方法从未被调用。已知:
InfoCommand已初始化并添加到CommandManager中CommandManager的onMessageReceived方法在消息发送时会被触发- 触发
onMessageReceived时,CommandManager的commands集合为空,且此时的CommandManager实例和初始化时的不是同一个
涉及代码:
InfoCommand类
public class InfoCommand extends Command { public InfoCommand(String name) { super(name); } @Override public void handle(MessageReceivedEvent event, String... params) { EmbedBuilder builder = new EmbedBuilder(); builder.setTitle("Test Title"); builder.setDescription("Test Description" ); builder.setFooter("Created by t0gepi"); builder.setColor(0xf45642); event.getChannel().sendTyping().queue(); event.getChannel().sendMessageEmbeds(builder.build()).queue(); } }
Main类
public class Main { public static JDA jda; public static void main(String[] args) throws LoginException { ResourceManager.init(); jda = JDABuilder.createDefault(ResourceManager.getProperty("discord.bottoken")).build(); jda.getPresence().setStatus(OnlineStatus.IDLE); jda.getPresence().setActivity(Activity.playing("Sleeping")); try { jda.awaitReady(); } catch (InterruptedException e) { e.printStackTrace(); } CommandManager commandManager = new CommandManager(); commandManager.addCommand(new InfoCommand("info")); jda.addEventListener(new CommandManager()); } }
CommandManager类
public class CommandManager extends ListenerAdapter { private Set<Command> commands; public CommandManager(){ this.commands = new HashSet<>(); } public void addCommand(Command command){ commands.add(command); } @Override public void onMessageReceived(@NotNull MessageReceivedEvent event) { String[] msg = event.getMessage().getContentRaw().split(" "); String prefix = ResourceManager.getProperty("command.prefix"); String[] params = null; if(!msg[0].startsWith(prefix)){ return; } if(msg.length > 1){ params = Arrays.copyOfRange(msg,1,msg.length); } Iterator<Command> iterator = commands.iterator(); Command command; while(iterator.hasNext()){ command = iterator.next(); if(command.getAliases().stream().anyMatch(alias -> msg[0].equalsIgnoreCase(prefix + alias))){ command.handle(event, params); return; } } // Do nothing here if command wasn't found. } }
问题原因
Main类中创建了两个独立的CommandManager实例:
- 第一个实例
commandManager添加了InfoCommand - 第二个实例是通过
new CommandManager()新建的,没有添加任何命令,却被注册为JDA的事件监听器
当消息事件触发时,JDA调用的是第二个空实例的onMessageReceived方法,自然找不到对应的命令,导致handle方法不执行。
解决方案
修改Main类的代码,将已经添加了命令的那个CommandManager实例注册为JDA监听器,而非新建实例:
public class Main { public static JDA jda; public static void main(String[] args) throws LoginException { ResourceManager.init(); jda = JDABuilder.createDefault(ResourceManager.getProperty("discord.bottoken")).build(); jda.getPresence().setStatus(OnlineStatus.IDLE); jda.getPresence().setActivity(Activity.playing("Sleeping")); try { jda.awaitReady(); } catch (InterruptedException e) { e.printStackTrace(); } CommandManager commandManager = new CommandManager(); commandManager.addCommand(new InfoCommand("info")); // 注册已添加命令的实例,而非新建 jda.addEventListener(commandManager); } }
内容的提问来源于stack exchange,提问作者smilly
相关产品推荐
相关产品推荐

