What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it? (25个答案)
2年前关闭。
这是我的代码:
private void bringData() {
final TextView mTextView = (TextView) findViewById(R.id.textView);
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://192.168.4.1:8080/";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
mTextView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
这是android文档中提供的默认值。我只更改了网址。
这是我的错误信息:
java.lang.StringIndexOutOfBoundsException:length = 28; regionStart = 1;
regionLength = 499
在java.lang.String.substring(String.java:1931)
在com.example.my.app.MainActivity $ 2.onResponse(MainActivity.java:50)
在com.example.my.app.MainActivity $ 2.onResponse(MainActivity.java:46)
在com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
在com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
在com.android.volley.ExecutorDelivery $ ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
在android.os.Handler.handleCallback(Handler.java:751)
在android.os.Handler.dispatchMessage(Handler.java:95)
在android.os.Looper.loop(Looper.java:154)
在android.app.ActivityThread.main(ActivityThread.java:6077)
在java.lang.reflect.Method.invoke(本机方法)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:865)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
在调试过程中,我在
mTextView.setText("Response is: "+ response.substring(0,500));
处看到了我的消息,但是textview从未更新,并且应用程序崩溃了。
具体来说,它在Looper.Java文件中的此处崩溃:
finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
traceTag为0。
我读到一些字符串范围是错误的,但是我找不到解决方法。
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)
错误说明
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个字符的子字符串。
解决方案:
使用三元运算符
?:
验证长度
mTextView.setText("Response is: "+
((response.length()>499) ? response.substring(0,500) : "length is too short"));
注意:三元运算符(
?:
)是
if else
的短表达式,但它是
not a statement表示它不能作为原子语句出现,因为它是
INVALID
,因为没有赋值
((someString.length()>499) ? someString.substring(0,500):"Invalid length");
if-else
增强可见度
String msg="Invalid Response";
if(response.length()>499){
msg=response.substring(0,500);
}
mTextView.setText("Response is: "+msg);
//or mTextView.setText("Response is: "+response);
什么是IndexOutOfBoundsException?
IndexOutOfBoundsException
是
RuntimeException
均值的子类
这是一个未经检查的异常,引发该异常以指示索引
某种形式的(例如数组,字符串或向量)
的范围,例如使用列表。
如
Documentation中所示
List<String> ls=new ArrayList<>();
ls.add("a");
ls.add("b");
ls.get(3); // will throw IndexOutOfBoundsException , list length is 2
预防措施:
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的其他变体/子类?
ArrayIndexOutOfBoundsException:这表明已使用非法索引访问了数组。索引为负数或大于或等于数组的大小,例如
int arr = {1,2,3}
int error = arr[-1]; // no negative index allowed
int error2 = arr[4]; // arr length is 3 as index range is 0-2
预防措施:
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
StringIndexOutOfBoundsException:由String方法抛出,以指示索引为负或大于字符串的大小。对于某些方法,例如charAt方法,当索引等于字符串的大小时,也会引发此异常。
String str = "foobar"; // length = 6
char error = str.charAt(7); // index input should be less than or equal to length-1
char error = str.charAt(-1); // cannot use negative indexes
预防措施:
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");
}
我怎样才能解决这个问题 ?
分析StackTrace
根据null,长度或有效索引验证输入字符串
使用调试或日志
使用通用异常捕获块
1.)分析StackTrace
如本文开头所示,stacktrace在初始消息中提供了有关发生位置,发生原因的必要信息,因此您可以简单地跟踪该代码并应用所需的解决方案。
例如原因
StringIndexOutOfBoundsException
然后查找您的
package name indicating your class file
然后转到该行并牢记原因,只需应用解决方案
如果您在文档中研究异常及其原因,这是一个领先的开始。
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) { // mTextView or response can be null
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 ");
}
其他参考
What is a NullPointerException, and how do I fix it?