java android android-volley

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



android android-volley (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)

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

Razón real

Su código tratando de crear una subcadena con

starting index = 0 ending index = 500

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

Soluciones:

  1. Validar longitud usando el 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 declaración significa que no puede ocurrir como una declaración atómica ya que esto 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 no verificada que se genera para indicar que un índice de algún tipo (como una matriz, una cadena o un vector) está fuera de rango, por ejemplo, usando List.

como se muestra en la Documentation

List<String> 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 del constructor de clases 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, p. Ej.

    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 : los métodos String lo lanzan 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 del í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 mayor que endIndex
  • Cuando endIndex - beginIndex resultado endIndex - beginIndex es menor que 0
  • Cuando la cadena / matriz de entrada está vacía

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

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

Cómo puedo arreglar esto ?

  1. Analizando StackTrace
  2. Validación de cadena de entrada contra nulidad, longitud o índices válidos
  3. Uso de depuración o registros
  4. Uso del bloque catch de excepción genérica

1.) Análisis de StackTrace

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

por ejemplo, la razón StringIndexOutOfBoundsException y luego busque 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 la razón, simplemente aplique la solución

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

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

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

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 examinar 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 wither system o el usuario también puede poner mensajes de registro utilizando Logs o mensajes Println

4.) Uso del bloque catch de excepción genérica

Try-catch bloques Try-catch siempre son útiles para manejar RuntimeExceptions por lo que puede usar múltiples bloques catch para manejar sus posibles problemas y dar 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 excepción NullPointerException y cómo la soluciono?

Esta pregunta ya tiene una respuesta aquí:

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

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

Este es mi mensaje de error:

java.lang.StringIndexOutOfBoundsException: longitud = 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 (Native Method) 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, veo que en mTextView.setText("Response is: "+ response.substring(0,500)); recibo mi mensaje pero la vista de texto nunca se actualiza y la aplicación falla.

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 cómo solucionarlo.