java StringIndexOutOfBoundsException: -1

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

java StringIndexOutOfBoundsException: -1

问题

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

java.lang.StringIndexOutOfBoundsException: String index out of range: -1
	at java.lang.String.substring(Unknown Source)
	at listener.CommandManager.onGuildMessageReceived(CommandManager.java:38)
	at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:395)
	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:165)
	at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:97)
	at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
	at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:881)
	at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:769)
	at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:748)
	at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:919)
	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)

以下是该类的代码:

package listener;

import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import tools.Settings;

import java.util.HashMap;
import java.util.Map;

import commands.*;

import assets.Command;

public class CommandManager extends ListenerAdapter {

	private static Map<String, Command> commands = new HashMap<String, Command>(); // 这里存储所有命令
	
	public static void init() { // 在这个方法中,我将所有命令放入 ArrayList 中。我在程序启动时调用它。
		
		commands.put("test", new TestCommand());
		
	}
	
	@Override
	public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
		
		String prefix = Settings.readSetting("Prefix"); // 在这里加载前缀。
		
		if(event.getMessage().getContentDisplay().startsWith(prefix)) {
			
			try {
				
				Command c = commands.get(event.getMessage().getContentDisplay().split(" ")[0].substring(prefix.length())); // 这里发生了错误。
				
				if(c != null) {
					
					c.execute(event);
					
				} else {
					
					event.getChannel().sendMessage("抱歉,该命令不存在").queue();
					
				}
				
			} catch(Exception e) {
				
				e.printStackTrace();
				
			}
		}
	}
	
}

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

英文:

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.

java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at listener.CommandManager.onGuildMessageReceived(CommandManager.java:38)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:395)
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:165)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:97)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:881)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:769)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:748)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:919)
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)

Here's the code of the class:

package listener;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import tools.Settings;
import java.util.HashMap;
import java.util.Map;
import commands.*;
import assets.Command;
public class CommandManager extends ListenerAdapter {
private static Map&lt;String, Command&gt; commands = new HashMap&lt;String, Command&gt;(); //here&#39;s where i store all the commands
public static void init() { //In this method i put all the commands in the ArrayList. I call it on Program Start.
commands.put(&quot;test&quot;, new TestCommand());
}
@Override
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
String prefix = Settings.readSetting(&quot;Prefix&quot;); //Here i load the prefix.
if(event.getMessage().getContentDisplay().startsWith(prefix)) {
try {
Command c = commands.get(event.getMessage().getContentDisplay().split(&quot; &quot;)[0].substring(prefix.length())); //Here occurs the error.
if(c != null) {
c.execute(event);
} else {
event.getChannel().sendMessage(&quot;Sorry, that command doesn&#39;t exist&quot;).queue();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
}

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返回的消息小于你的前缀长度会发生什么情况?

实际示例:

// 假设这是输入:
String prefix = "Hello";
String messageContentDisplay = "Hello Jack";

// 你的代码执行:
String[] segments = messageContentDisplay.split(" ");
String prefixInMessage = segments[0];
String subMessage = prefixInMessage.substring(prefix.length()); // 这是没有意义的。

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

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

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:

// assume this input:
String prefix = &quot;Hello&quot;;
String messageContentDisplay = &quot;Hello Jack&quot;;

// your code does:
String[] segments = messageContentDisplay.split(&quot; &quot;);
String prefixInMessage = segments[0];
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:

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

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:

确定