web-dev-qa-db-fra.com

Qu'est-ce que IndexOutOfBoundsException? Comment puis-je le réparer?

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

C'est la valeur par défaut donnée dans la documentation Android. J'ai seulement changé l'url.

Voici mon message d'erreur:

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

Pendant le débogage, je vois qu'à mTextView.setText("Response is: "+ response.substring(0,500)); mon message est remis à moi mais le textview n'est jamais mis à jour et l'application plante.

Plus précisément, il se bloque ici à l'intérieur du fichier Looper.Java:

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

traceTag vaut 0.

J'ai lu que certaines limites de chaîne sont incorrectes mais je ne peux pas trouver de solution.

7
traveller
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) 

Description de l'erreur

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

Raison réelle

Votre code essaie de créer une sous-chaîne avec

starting index = 0
ending index = 500

bien que la longueur réelle de votre chaîne de réponse soit = ​​28, la longueur de la chaîne n'est pas suffisante pour créer une sous-chaîne de 500 caractères.

Solutions:

  1. Valider la longueur en utilisant l'opérateur ternaire ?:

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

    Remarque: L'opérateur ternaire (?:) Est une courte expression de if else Mais c'est pas une instruction signifie qu'il ne peut pas apparaître comme une instruction atomique comme c'est le cas INVALID car il n'y a pas d'affectation

    ((someString.length()>499) ? someString.substring(0,500):"Invalid length");
    
  2. if-else Améliore la visibilité

    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'est-ce que IndexOutOfBoundsException?

IndexOutOfBoundsException est une sous-classe de RuntimeException signifie qu'il s'agit d'une exception non vérifiée qui est levée pour indiquer qu'un index quelconque (comme un tableau, une chaîne ou un vecteur) est out of range.eg en utilisant List.

comme indiqué dans le Documentation

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

Prévention :

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

Utilisation du constructeur de classe avec un message d'index ou de chaîne

public IndexOutOfBoundsException() {
    super();
}

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

Quelles sont les autres variantes/sous-classes d'IndexOutOfBoundsException?

  • ArrayIndexOutOfBoundsException : cela indique qu'un tableau a été accédé avec un index illégal. L'indice est soit négatif, soit supérieur ou égal à la taille du tableau, par exemple

    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
    

Prévention :

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 : Ceci est levé par les méthodes String pour indiquer qu'un index est négatif ou supérieur à la taille de la chaîne. Pour certaines méthodes telles que la méthode charAt, cette exception est également levée lorsque l'index est égal à la taille de la chaîne.

    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
    

Prévention :

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

Remarque: length() est une fonction de String classe et length est un champ associatif de un array.

Pourquoi ces exceptions se produisent-elles?

  • Utilisation de l'index négatif avec les fonctions arrays ou charAt, substring
  • BeginIndex est inférieur à 0 Ou endIndex est supérieur à la longueur de la chaîne d'entrée pour créer substring ou beginIndex est plus grand que endIndex
  • Lorsque le résultat de endIndex - beginIndex Est inférieur à 0
  • Lorsque la chaîne/le tableau d'entrée est vide

INFO: Il incombe à la JVM de créer l'objet d'exception approprié et de le transmettre à l'endroit où il s'est produit en utilisant throw mot-clé comme ou vous pouvez également le faire manuellement en utilisant le mot-clé throw aussi.

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

Comment puis-je réparer cela ?

  1. Analyse de StackTrace
  2. Validation de la chaîne d'entrée par rapport à la nullité, à la longueur ou aux index valides
  3. Utilisation du débogage ou des journaux
  4. Utilisation du bloc de capture d'exception générique

1.) Analyse de StackTrace

Comme indiqué au début de cet article, stacktrace fournit les informations nécessaires dans les messages initiaux sur l'endroit où il se produit, pourquoi il se produit afin que vous puissiez simplement suivre ce code et appliquer la solution requise.

par exemple la raison StringIndexOutOfBoundsException puis recherchez votre package name indicating your class file puis allez sur cette ligne et en gardant la raison à l'esprit, appliquez simplement la solution

C'est une longueur d'avance si vous étudiez l'exception et sa cause également dans la documentation.

2.) Validation de la chaîne d'entrée par rapport à la nullité, à la longueur ou aux index valides

En cas d'incertitude lorsque vous ne connaissez pas l'entrée réelle comme la réponse provient du serveur (ou peut-être que c'est une erreur ou rien) ou de l'utilisateur, il est toujours préférable de couvrir tous les cas inattendus mais croyez-moi, peu d'utilisateurs aiment toujours repousser les limites des tests , utilisez donc input!=null && input.length()>0 ou pour les index, vous pouvez utiliser l'opérateur ternaire ou if-else vérification des limites conditions

3.) Utilisation du débogage ou des journaux

Vous pouvez tester l'environnement d'exécution de votre projet en mode débogage en ajoutant des points d'arrêt dans votre projet et le système s'arrêtera là pour attendre votre prochaine action et pendant ce temps, vous pouvez regarder les valeurs des variables et d'autres détails.

Les journaux sont comme des points de contrôle, donc lorsque votre contrôle franchit ce point, ils génèrent des détails.En gros, ce sont des messages informatifs donnés par le système Wither ou l'utilisateur peut également mettre des messages de journalisation à l'aide de messages Logs ou Println

4.) Utilisation du bloc catch d'exception générique

Les blocs Try-catch Sont toujours utiles pour gérer RuntimeExceptions afin que vous puissiez utiliser plusieurs blocs catch pour gérer vos éventuels problèmes et donner les détails appropriés

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

Autres références

Qu'est-ce qu'une NullPointerException, et comment puis-je la corriger?

13
Pavneet_Singh