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:
-
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 deif else
pero no es una declaración significa que no puede ocurrir como una declaración atómica ya que esto esINVALID
porque no hay asignación((someString.length()>499) ? someString.substring(0,500):"Invalid length");
-
if-else
mejora la visibilidadString 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 deRuntimeException
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
ocharAt
, funciones desubstring
-
BeginIndex es menor que
0
o endIndex es mayor que la longitud de la cadena de entrada para crear unasubstring
o beginIndex es mayor que endIndex -
Cuando
endIndex - beginIndex
resultadoendIndex - beginIndex
es menor que0
- 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 ?
- Analizando StackTrace
- Validación de cadena de entrada contra nulidad, longitud o índices válidos
- Uso de depuración o registros
- 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.