java StringIndexOutOfBoundsException: -1

huangapple go评论118阅读模式
英文:

java StringIndexOutOfBoundsException: -1

问题

我正在尝试编写一个 Discord 机器人。
现在我遇到了以下问题:
首先,我使用字符串前缀加载设置,代码如下:String prefix = Setttings.readSetting("Prefix");
然后,我测试从 Discord 收到的消息是否以前缀开头。
如果测试通过,我会截取消息并提取命令本身,然后执行该命令所在类的方法。但是这是我的问题:
当我的前缀长度大于1个字符时,我会遇到 StringIndexOutOfBoundsException。

  1. java.lang.StringIndexOutOfBoundsException: String index out of range: -1
  2. at java.lang.String.substring(Unknown Source)
  3. at listener.CommandManager.onGuildMessageReceived(CommandManager.java:38)
  4. at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:395)
  5. at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
  6. at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:64)
  7. at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:165)
  8. at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:97)
  9. at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
  10. at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:881)
  11. at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:769)
  12. at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:748)
  13. at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:919)
  14. at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
  15. at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
  16. at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
  17. at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
  18. at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
  19. at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
  20. at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)

以下是该类的代码:

  1. package listener;
  2. import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
  3. import net.dv8tion.jda.api.hooks.ListenerAdapter;
  4. import tools.Settings;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. import commands.*;
  8. import assets.Command;
  9. public class CommandManager extends ListenerAdapter {
  10. private static Map<String, Command> commands = new HashMap<String, Command>(); // 这里存储所有命令
  11. public static void init() { // 在这个方法中,我将所有命令放入 ArrayList 中。我在程序启动时调用它。
  12. commands.put("test", new TestCommand());
  13. }
  14. @Override
  15. public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
  16. String prefix = Settings.readSetting("Prefix"); // 在这里加载前缀。
  17. if(event.getMessage().getContentDisplay().startsWith(prefix)) {
  18. try {
  19. Command c = commands.get(event.getMessage().getContentDisplay().split(" ")[0].substring(prefix.length())); // 这里发生了错误。
  20. if(c != null) {
  21. c.execute(event);
  22. } else {
  23. event.getChannel().sendMessage("抱歉,该命令不存在").queue();
  24. }
  25. } catch(Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. }

有人知道这个错误和/或如何修复吗?
谢谢。

英文:

I am trying to write a discord bot.
Now i have the following problem:
First i load the prefix with String prefix = Setttings.readSetting("Prefix");
Then i test if the message received from the discord starts with the prefix.
If this test passes, i crop the Message and extract the command itself and execute
the method in the class of the method. But here's my problem:
When my prefix is longer than 1 character i get a StringIndexOutOfBoundsException.

  1. java.lang.StringIndexOutOfBoundsException: String index out of range: -1
  2. at java.lang.String.substring(Unknown Source)
  3. at listener.CommandManager.onGuildMessageReceived(CommandManager.java:38)
  4. at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:395)
  5. at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
  6. at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:64)
  7. at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:165)
  8. at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:97)
  9. at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
  10. at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:881)
  11. at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:769)
  12. at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:748)
  13. at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:919)
  14. at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
  15. at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
  16. at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
  17. at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
  18. at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
  19. at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
  20. at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)

Here's the code of the class:

  1. package listener;
  2. import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
  3. import net.dv8tion.jda.api.hooks.ListenerAdapter;
  4. import tools.Settings;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. import commands.*;
  8. import assets.Command;
  9. public class CommandManager extends ListenerAdapter {
  10. private static Map&lt;String, Command&gt; commands = new HashMap&lt;String, Command&gt;(); //here&#39;s where i store all the commands
  11. public static void init() { //In this method i put all the commands in the ArrayList. I call it on Program Start.
  12. commands.put(&quot;test&quot;, new TestCommand());
  13. }
  14. @Override
  15. public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
  16. String prefix = Settings.readSetting(&quot;Prefix&quot;); //Here i load the prefix.
  17. if(event.getMessage().getContentDisplay().startsWith(prefix)) {
  18. try {
  19. Command c = commands.get(event.getMessage().getContentDisplay().split(&quot; &quot;)[0].substring(prefix.length())); //Here occurs the error.
  20. if(c != null) {
  21. c.execute(event);
  22. } else {
  23. event.getChannel().sendMessage(&quot;Sorry, that command doesn&#39;t exist&quot;).queue();
  24. }
  25. } catch(Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. }
  30. }

Does anyone know the error and/or how to fix it?
Thank you.

答案1

得分: 0

关于特定的异常:https://www.geeksforgeeks.org/understanding-array-indexoutofbounds-exception-in-java/

通常情况下,如果以某种方式访问数组(或字符串),使参数索引超出数组的索引范围,就会引发“IndexOutOfBoundsException”异常。

在你的情况下,异常被抛出,可能是因为你执行的字符串分割操作可能没有返回数组中索引为0的值,其长度足够长以包含“prefix.length()”。或者换个方式说:如果getMessage返回的消息小于你的前缀长度会发生什么情况?

实际示例:

  1. // 假设这是输入:
  2. String prefix = "Hello";
  3. String messageContentDisplay = "Hello Jack";
  4. // 你的代码执行:
  5. String[] segments = messageContentDisplay.split(" ");
  6. String prefixInMessage = segments[0];
  7. String subMessage = prefixInMessage.substring(prefix.length()); // 这是没有意义的。

我相信你实际想要的是截取前缀,可以这样实现:

  1. String displayContent = event.getMessage().getContentDisplay();
  2. String[] segments = displayContent.split(" ");
  3. if (segments.length > 1) {
  4. Command c = commands.get(displayContent.substring(segments[0].length));
  5. }
英文:

First, about the specific exception: https://www.geeksforgeeks.org/understanding-array-indexoutofbounds-exception-in-java/

An IndexOutOfBoundsException is usually thrown, if an array (or String) is accessed in such a way, that the argument index is outside the array's index range.

In your case, the exception is thrown, because the string split you perform probably does not return a value in the array at index 0 that is as long as prefix.length(). Or to put it another way: What happens if the message returned by getMessage is smaller than the length of your prefix?

Practical example:

  1. // assume this input:
  2. String prefix = &quot;Hello&quot;;
  3. String messageContentDisplay = &quot;Hello Jack&quot;;
  4. // your code does:
  5. String[] segments = messageContentDisplay.split(&quot; &quot;);
  6. String prefixInMessage = segments[0];
  7. String subMessage = prefixInMessage.substring(prefix.length()); // This makes no sense.

I believe what you actually want is to cut the prefix, which would work like this:

  1. String displayContent = event.getMessage().getContentDisplay();
  2. String[] segments = displayContent.split(&quot; &quot;);
  3. if (segments.length &gt; 1) {
  4. Command c = commands.get(displayContent.substring(segments[0].length));
  5. }

huangapple
  • 本文由 发表于 2020年5月4日 21:44:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/61593723.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定