什么是 StringIndexOutOfBoundsException?我该如何解决?

Posted

技术标签:

【中文标题】什么是 StringIndexOutOfBoundsException?我该如何解决?【英文标题】:What is a StringIndexOutOfBoundsException? How can I fix it? 【发布时间】:2017-02-21 17:03:45 【问题描述】:

这是我的代码:

    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: 长度=28;区域开始=1; 区域长度=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)); 我的消息已发送给我,但文本视图从未更新,应用程序崩溃。

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

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

traceTag 为 0。

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

【问题讨论】:

阅读 StringIndexOutOfBoundsException 的文档。然后阅读您收到的错误信息。 相关:What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it? 虽然此异常与 ArrayIndexOutOfBoundsException 的异常有关,但它不是重复的。例外情况不同。原因是不同的(尽管类似)。最重要的是,这个问题及其答案没有提及这个例外。 【参考方案1】:
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?

IndexOutOfBoundsExceptionRuntimeException 的子类 这是一个未经检查的异常,被抛出以指示索引 某种类型的(例如数组、字符串或向量)已出 范围。例如使用列表。

如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 类的函数,lengtharray 的关联字段。

为什么会出现这些异常?

arrayscharAt , substring 函数中使用负索引 BeginIndex 小于 0 或 endIndex 大于要创建的输入字符串的长度 substring 或 beginIndex 大于 endIndex 当endIndex - beginIndex结果小于0 当输入字符串/数组为空时

INFO : JVM 的工作是创建适当异常的对象并将其传递到使用 throw 关键字之类的位置,或者您也可以使用 @ 手动完成987654358@也是关键字。

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

我该如何解决这个问题?

    分析 StackTrace 根据空值、长度或有效索引验证输入字符串 使用调试或日志 使用通用异常捕获块

1.) 分析 StackTrace

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

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

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

2.) 根据 nullity、length 或有效索引验证输入字符串

如果您不知道实际输入(例如响应来自服务器(或者可能是错误或什么都没有))或用户的不确定性,那么最好涵盖所有意外情况尽管相信我很少有用户总是喜欢挑战测试的极限所以使用input!=null &amp;&amp; input.length()&gt;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?

【讨论】:

谢谢,但现在它只显示“你想显示的任何内容”。所以response.length()不超过499。 @traveller 因为正如我在回答中所说,您的回复长度为 28,因此您无法创建 500 个字符的字符串以及“无论您想显示什么”,它只是一个string ,所以你在这里给出的任何东西都会显示出来 @traveller 检查更新的答案是否清晰,也可以尝试注释代码 我想我现在明白了。我的字符串只有 28 个字符,我正在尝试创建一个长度为 500 的子字符串,显然我做不到,但如果我的字符串长度超过 500 个字符,我就能做到。 我要问,为什么要 500 个字符?这是文本视图的最大长度吗?

以上是关于什么是 StringIndexOutOfBoundsException?我该如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

时间是什么?时间同步是什么?GPS北斗卫星授时又是什么?

什么是拉电流,什么是灌电流?什么是吸收电流 ?

在java中,OOA是什么?OOD是什么?OOP是什么?

什么是DIV,全称是什么?

什么是抢占/什么是可抢占内核?到底有什么好处呢?

什么是 JNDI?它的基本用途是什么?什么时候使用?