Java 什么是 IndexOutOfBoundsException?我该如何解决?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40006317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:37:36  来源:igfitidea点击:

What is IndexOutOfBoundsException? How can I fix it?

javaandroidandroid-volley

提问by traveller

This is my code:

这是我的代码:

    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);
}

It's the default given from the android documentation. I only changed the url.

这是 android 文档中给出的默认值。我只更改了网址。

This is my 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)

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:

During debugging I see that at mTextView.setText("Response is: "+ response.substring(0,500));my message is delivered to me but the textview is never updated and the app crashes.

在调试期间,我看到mTextView.setText("Response is: "+ response.substring(0,500));我的消息已发送给我,但文本视图从未更新并且应用程序崩溃。

Specifically, it crashes here inside the Looper.Java file:

具体来说,它在 Looper.Java 文件中崩溃了:

finally {
if (traceTag != 0) {
   Trace.traceEnd(traceTag);
} 

traceTag is 0.

跟踪标签为 0。

I read that some string bounds are wrong but I cannot find out how to fix it.

我读到一些字符串边界是错误的,但我不知道如何修复它。

采纳答案by Pavneet_Singh

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.onResponse(MainActivity.java:50) at     
    com.example.my.app.MainActivity.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 MainActivityonResponse
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

Actual Reason

实际原因

Your code trying to create a substring with

您的代码试图创建一个子字符串

starting index = 0
ending index = 500

though your actual response string length is = 28, so String length is not long enough to create a substring of 500 characters.

尽管您的实际响应字符串长度为 = 28,但字符串长度不足以创建 500 个字符的子字符串。

Solutions :

解决方案:

  1. 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 elsebut it is not a statementmean it cannot occur as an atomic statement as this is INVALIDbecause there is no assignment

    ((someString.length()>499) ? someString.substring(0,500):"Invalid length");
    
  2. if-elseenhances the visibility

    String msg="Invalid Response";
    if(response.length()>499){
        msg=response.substring(0,500);
    }
    mTextView.setText("Response is: "+msg);
    
    //or     mTextView.setText("Response is: "+response);
    
  1. 使用三元运算符验证长度 ?:

    mTextView.setText("Response is: "+ 
       ((response.length()>499) ? response.substring(0,500) : "length is too short"));
    

    注意:三元运算符 ( ?:) 是 的简短表达式,if else但它不是语句,这意味着它不能作为原子语句出现,因为这是INVALID因为没有赋值

    ((someString.length()>499) ? someString.substring(0,500):"Invalid length");
    
  2. 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);
    

What is IndexOutOfBoundsException?

什么是 IndexOutOfBoundsException?

IndexOutOfBoundsExceptionis a subclass of RuntimeExceptionmean it is an unchecked exception which is thrown to indicate that an index of some sort (such as to an array, to a string, or to a vector) is out of range.e.g using List.

IndexOutOfBoundsExceptionRuntimeExceptionmean的子类,它是一个未经检查的异常,抛出该异常以指示某种索引(例如数组、字符串或向量)超出范围。例如,使用 List。

as shown in the Documentation

文档中所示

List<String> ls=new ArrayList<>();
      ls.add("a");
      ls.add("b");
      ls.get(3); // will throw IndexOutOfBoundsException , list length is 2
List<String> ls=new ArrayList<>();
      ls.add("a");
      ls.add("b");
      ls.get(3); // will throw IndexOutOfBoundsException , list length is 2

Prevention:

预防

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

Class Constructor usage with index or string message

带有索引或字符串消息的类构造函数用法

public IndexOutOfBoundsException() {
    super();
}

public IndexOutOfBoundsException(String s) {
    super(s);
}

Which are other variations/sub-classes of IndexOutOfBoundsException?

IndexOutOfBoundsException 的其他变体/子类有哪些?

  • ArrayIndexOutOfBoundsException: This indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array for e.g

    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
    
  • 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
    

Prevention:

预防

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: This is thrown by String methods to indicate that an index is either negative or greater than the size of the string. For some methods such as the charAt method, this exception also is thrown when the index is equal to the size of the string.

    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
    
  • 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
    

Prevention:

预防

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

Note:length()is a function of Stringclass and lengthis a associative field of an array.

注意:length()String类的函数,length是 的关联域array

Why these exception occur?

为什么会出现这些异常?

  • Usage of Negative index with arraysor charAt, substringfunctions
  • BeginIndex is less than 0or endIndex is greater than the length of input string to create substringor beginIndex is larger than the endIndex
  • When endIndex - beginIndexresult is less than 0
  • When input string/array is empty
  • 负索引与arraysor charAt,substring函数的使用
  • BeginIndex 小于0或 endIndex 大于要创建的输入字符串的长度substring或 beginIndex 大于 endIndex
  • endIndex - beginIndex结果小于0
  • 当输入字符串/数组为空时

INFO :It is job of JVM to create the object of appropriate exception and pass it to the place of , where it occurred using throwkeyword like or you can also do it manually using throwkeyword too.

信息:JVM 的工作是创建适当的异常对象并将其传递到使用throw关键字 like发生的地方,或者您也可以使用throw关键字手动完成。

if (s == null) {
    throw new IndexOutOfBoundsException("null");
}

How can I fix this ?

我怎样才能解决这个问题 ?

  1. Analyzing StackTrace
  2. Validating input string against nullity , length or valid indexes
  3. Using Debugging or Logs
  4. Using Generic Exception catch block
  1. 分析堆栈跟踪
  2. 根据空值、长度或有效索引验证输入字符串
  3. 使用调试或日志
  4. 使用通用异常捕获块

1.) Analyzing StackTrace

1.) 分析 StackTrace

As shown at the beginning of this post , stacktrace provides the necessary information in the initial messages about where it happen , why it happen so you can simply trace that code and apply the required solution .

如本文开头所示,stacktrace 在初始消息中提供了有关发生位置、发生原因的必要信息,因此您可以简单地跟踪该代码并应用所需的解决方案。

for e.g the reason StringIndexOutOfBoundsExceptionand then look for your package name indicating your class filethen go to that line and keeping the reason in mind , simply apply the solution

例如原因 StringIndexOutOfBoundsException,然后寻找您的package name indicating your class file然后转到该行并牢记原因,只需应用解决方案

It's a head start if you study about the exception and its cause as well in documentation.

如果您在文档中研究异常及其原因,这是一个良好的开端。

2.) Validating input string against nullity , length or valid indexes

2.) 针对空值、长度或有效索引验证输入字符串

In case of uncertainty when you don't know about the actual input like response is coming from server (or maybe it's an error or nothing) or user then it's always better to cover all the unexpected cases though believe me few users always like to push the limits of testingso use input!=null && input.length()>0or for indexes, you can use the ternary operator or if-elseboundary check conditions

在不确定的情况下,当您不知道响应来自服务器(或者可能是错误或什么都没有)或用户的实际输入时,那么覆盖所有意外情况总是更好,尽管相信我很少有用户总是喜欢推送测试的限制因此使用input!=null && input.length()>0或对于索引,您可以使用三元运算符或if-else边界检查条件

3.) Using Debugging or Logs

3.) 使用调试或日志

You can test the running environment of your project in debug mode by adding break-points in your project and system will stop there to wait for your next action and meanwhile you can look into the values of variables and other details.

您可以通过在项目中添加断点来在调试模式下测试项目的运行环境,系统将停在那里等待您的下一步操作,同时您可以查看变量的值和其他详细信息。

Logs are just like check-points so when your control cross this point they generate details , basically they are informative messages given by wither system or user can also put logging messages using either Logs or Println messages

日志就像检查点,所以当你的控件跨越这一点时,它们会生成详细信息,基本上它们是由枯萎系统提供的信息性消息,或者用户也可以使用 Logs 或 Println 消息放置日志消息

4.) Using Generic Exception catch block

4.) 使用通用异常捕获块

Try-catchblocks are always useful to handle RuntimeExceptionsso you can use multiple catchblock along to handle your possible issues and to give appropriate details

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 ");
}

Further References

进一步参考

What is a NullPointerException, and how do I fix it?

什么是 NullPointerException,我该如何解决?