¿Qué es IndexOutOfBoundsException? ¿Cómo puedo arreglarlo?

Este es mi código:

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() { @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); } 

Es el valor predeterminado dado de la documentación de Android. Solo cambié la url.

Este es mi mensaje de error:

java.lang.StringIndexOutOfBoundsException: length = 28; regionStart = 1; regionLength = 499 en java.lang.String.substring (String.java:1931) en com.example.my.app.MainActivity $ 2.onResponse (MainActivity.java:50) en com.example.my.app.MainActivity $ 2. onResponse (MainActivity.java:46) en com.android.volley.toolbox.StringRequest.deliverResponse (StringRequest.java:60) en com.android.volley.toolbox.StringRequest.deliverResponse (StringRequest.java:30) en com.android .volley.ExecutorDelivery $ ResponseDeliveryRunnable.run (ExecutorDelivery.java:99) en android.os.Handler.handleCallback (Handler.java:751) en android.os.Handler.dispatchMessage (Handler.java:95) en android.os. Looper.loop (Looper.java:154) en android.app.ActivityThread.main (ActivityThread.java:6077) en java.lang.reflect.Method.invoke (Método nativo) en com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:865) en com.android.internal.os.ZygoteInit.main (ZygoteInit.java:755)

Durante la depuración lo veo en mTextView.setText("Response is: "+ response.substring(0,500)); mi mensaje se me entrega, pero la vista de texto nunca se actualiza y la aplicación se cuelga.

Específicamente, se bloquea aquí dentro del archivo Looper.Java:

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

traceTag es 0.

Leí que algunos límites de cadena son incorrectos, pero no puedo encontrar la manera de solucionarlo.

 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 de descripción

 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 

Motivo real

Tu código intenta crear una subcadena con

 starting index = 0 ending index = 500 

aunque la longitud de la cadena de respuesta real es = 28, por lo que la longitud de la cadena no es lo suficientemente larga como para crear una subcadena de 500 caracteres.

Soluciones:

  1. Valide la longitud usando un operador ternario ?:

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

    Nota: El operador ternario ( ?: 🙂 Es una expresión corta de if else pero no es una statement, significa que no puede ocurrir como una statement atómica ya que es INVALID porque no hay asignación.

     ((someString.length()>499) ? someString.substring(0,500):"Invalid length"); 
  2. if-else mejora la visibilidad

     String msg="Invalid Response"; if(response.length()>499){ msg=response.substring(0,500); } mTextView.setText("Response is: "+msg); //or mTextView.setText("Response is: "+response); 

¿Qué es IndexOutOfBoundsException?

IndexOutOfBoundsException es una subclase de RuntimeException significa que es una excepción sin IndexOutOfBoundsException se IndexOutOfBoundsException para indicar que un índice de algún tipo (como una matriz, una cadena o un vector) está fuera de range.eg usando List.

como se muestra en la Documentación

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

Prevención :

 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 

Uso de Class Constructor con índice o mensaje de cadena

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

¿Cuáles son otras variaciones / subclases de IndexOutOfBoundsException?

  • ArrayIndexOutOfBoundsException : Esto indica que se ha accedido a una matriz con un índice ilegal. El índice es negativo o mayor o igual que el tamaño de la matriz, por ejemplo

     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 

Prevención :

 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 : esto se lanza mediante métodos String para indicar que un índice es negativo o mayor que el tamaño de la cadena. Para algunos métodos, como el método charAt, esta excepción también se produce cuando el índice es igual al tamaño de la cadena.

     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 

Prevención :

 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 

Nota: length() es una función de String clase String y length es un campo asociativo de una array .

¿Por qué ocurren estas excepciones?

  • Uso de índice negativo con arrays o charAt , funciones de substring
  • BeginIndex es menor que 0 o endIndex es mayor que la longitud de la cadena de entrada para crear una substring o beginIndex es más grande que endIndex
  • Cuando endIndex - beginIndex result es menor que 0
  • Cuando la cadena / matriz de entrada está vacía

INFORMACIÓN: Es tarea de JVM crear el objeto de la excepción apropiada y pasarlo al lugar de, donde ocurrió usando throw keyword o también puede hacerlo manualmente usando throw keyword también.

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

Cómo puedo arreglar esto ?

  1. Analizando StackTrace
  2. Validación de cadena de entrada en contra de nulidad, longitud o índices válidos
  3. Usar depuración o registros
  4. Usar el bloque catch genérico Exception

1.) Analizando StackTrace

Como se muestra al comienzo de esta publicación, stacktrace proporciona la información necesaria en los mensajes iniciales sobre dónde ocurre, por qué ocurre, de modo que puede simplemente rastrear ese código y aplicar la solución requerida.

por ejemplo, el motivo StringIndexOutOfBoundsException y luego buscar el package name indicating your class file de su package name indicating your class file luego vaya a esa línea y, teniendo en cuenta el motivo, simplemente aplique la solución

Es una ventaja si estudias la excepción y su causa también en la documentación.

2.) Validación de cadena de entrada en contra de nulidad, longitud o índices válidos

En caso de incertidumbre cuando usted no sabe acerca de la entrada real, como la respuesta proviene del servidor (o tal vez es un error o nada) o usuario, siempre es mejor cubrir todos los casos inesperados, aunque créanme que a pocos usuarios siempre les gusta presionar los límites de la prueba así que use input!=null && input.length()>0 o para los índices, puede usar el operador ternario o if-else condiciones de verificación de límites

3.) Uso de depuración o registros

Puede probar el entorno de ejecución de su proyecto en modo de depuración agregando puntos de interrupción en su proyecto y el sistema se detendrá allí para esperar su próxima acción y mientras tanto puede ver los valores de las variables y otros detalles.

Los registros son como puntos de control, por lo que cuando su control cruza este punto generan detalles, básicamente son mensajes informativos proporcionados por el sistema marchito o el usuario también puede poner mensajes de registro usando Logs o Println messages

4.) Usando el bloque catch genérico de excepción

Try-catch bloques Try-catch siempre son útiles para manejar RuntimeExceptions por lo que puede usar varios bloque catch para manejar sus posibles problemas y dar los detalles apropiados

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

Referencias adicionales

¿Qué es una NullPointerException y cómo la soluciono?