Error Message:
java.lang.StringIndexOutOfBoundsException: length=28; regionStart=1;
regionLength=499 at java.lang.String.substring(String.java:1931) at
com.example.my.app.MainActivity$2.onResponse(MainActivity.java:50) at
com.example.my.app.MainActivity$2.onResponse(MainActivity.java:46) at
com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60) at
com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30) at
com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99) at android.os.Handler.handleCallback(Handler.java:751) at
android.os.Handler.dispatchMessage(Handler.java:95) at
android.os.Looper.loop(Looper.java:154) at
android.app.ActivityThread.main(ActivityThread.java:6077) at
java.lang.reflect.Method.invoke(Native Method) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Error Description
There is an IndexOutOfBound exception occurred in your MainActivity class
Inside second inner class's OnResponse function as shown MainActivity$2onResponse
on line 46 which basically occurred during substring operation in String.java line 1931
which was invoked from StringRequest.deliverResponse at line 60,
which was invoked from StringRequest.deliverResponse at line 30,
which was invoked from ExecutorDelivery.java at line 99,
which intially started from ZygoteInit$MethodAndArgsCaller's run function
and reached up-to main thread of ActivityThread.main=>looper=>handler
实际原因
您的代码尝试创建一个子字符串,但是
starting index = 0
ending index = 500
虽然您实际的响应字符串长度为28,因此字符串长度不足以创建500个字符的子字符串。
解决方案:
Validate length using ternary operator ?:
mTextView.setText("Response is: "+
((response.length()>499) ? response.substring(0,500) : "length is too short"));
Note : Ternary operator (?:
) is a short expression of if else
but it is not a statement mean it cannot occur as an atomic statement as this is INVALID
because there is no assignment
((someString.length()>499) ? someString.substring(0,500):"Invalid length")
if-else
enhances the visibility
String msg="Invalid Response";
if(response.length()>499){
msg=response.substring(0,500);
}
mTextView.setText("Response is: "+msg);
什么是IndexOutOfBoundsException?
IndexOutOfBoundsException
是RuntimeException
的一个子类,意味着它是一个未经检查的异常,用于指示某种索引(例如数组、字符串或向量)超出范围,例如使用List。
如文档所示。
List<String> ls=new ArrayList<>();
ls.add("a");
ls.add("b");
ls.get(3);
预防措施 :
String str = "";
int index =3;
if(index < ls.size()) // check, list size must be greater than index
str = ls.get(index);
else
// print invalid index or other stuff
使用索引或字符串消息的类构造函数用法
public IndexOutOfBoundsException() {
super();
}
public IndexOutOfBoundsException(String s) {
super(s);
}
IndexOutOfBoundsException有哪些其他变体/子类?
预防措施 :
int num = "";
int index=4;
if(index < arr.length) // check, array length must be greater than index
num = arr[index];
else
// print invalid index or other stuff
预防措施:
String name = "FooBar";
int index = 7;
char holder = '';
if(index < name.length()) // check, String length must be greater than index
holder = name.charAt(index) ;
else
// print invalid index or other stuff
注意:length()
是String
类的函数,而length
是array
的一个关联字段。
为什么会发生这些异常?
- 在使用
arrays
或charAt
,substring
函数时使用了负索引
- BeginIndex小于
0
或endIndex大于输入字符串长度以创建substring
,或者beginIndex大于endIndex
endIndex - beginIndex
的结果小于0
- 输入的字符串/数组为空
信息: JVM的工作是创建适当的异常对象并使用throw
关键字将其传递到它发生的地方,也可以使用throw
关键字手动执行该操作。
if (s == null) {
throw new IndexOutOfBoundsException("null");
}
我该如何修复这个问题?
1.分析StackTrace
2.针对空值、长度或有效索引验证输入字符串
3.使用调试或日志记录
4.使用通用异常捕获块
1.) 分析StackTrace
如本文开头所示,StackTrace提供了有关发生位置和原因的必要信息,因此您可以简单地跟踪该代码并应用所需的解决方案。
例如,查看StringIndexOutOfBoundsException的原因,然后查找指示类文件的包名称,然后转到该行并牢记原因,简单地应用解决方案。
如果您在文档中学习异常及其原因,那么这是一个良好的起点。
2.) 针对空值、长度或有效索引验证输入字符串
在你不确定实际输入(比如来自服务器的响应,或者可能是错误或什么都没有)或用户时,最好涵盖所有意外情况,尽管相信我,一些用户总是喜欢推动测试的极限,因此使用
input!=null && input.length()>0
或对于索引,您可以使用三元运算符或
if-else
边界检查条件。
3.) 使用调试或日志
您可以通过在项目中添加断点以调试模式测试项目的运行环境,系统会在那里停止等待您的下一个操作,同时您可以查看变量和其他细节的值。
日志就像检查点一样,当您的控制穿过这个点时,它们生成详细信息,基本上它们是由系统或用户使用Logs或Println消息放置日志消息的信息性消息。
4.) 使用通用异常捕获块
try-catch
块总是有用的,用于处理
RuntimeExceptions
,因此您可以使用多个
catch
块来处理可能的问题并提供适当的详细信息。
try {
mTextView.setText("Response is: "+ response.substring(0,500));
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
System.out,println("Invalid indexes or empty string");
}
catch (NullPointerException e) {
e.printStackTrace();
System.out,println("Something went wrong ,missed initialization");
}
catch (Exception e) {
e.printStackTrace();
System.out,println("Something unexpected happened , move on or can see stacktrace ");
}
进一步参考资料
什么是NullPointerException,如何修复它?
ArrayIndexOutOfBoundsException
相关,但它不是一个副本。这个异常是不同的。原因是不同的(尽管类似)。最重要的是,那个问题及其答案没有提到这个异常。 - Stephen C