web-dev-qa-db-ja.com

IndexOutOfBoundsExceptionとは何ですか?どうすれば修正できますか?

これは私のコードです:

_    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のドキュメントから与えられたデフォルトです。私はURLを変更しただけです。

これは私のエラーメッセージです:

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)

デバッグ中にmTextView.setText("Response is: "+ response.substring(0,500));でメッセージが配信されますが、textviewが更新されず、アプリがクラッシュします。

具体的には、ここでLooper.Javaファイル内でクラッシュします。

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

traceTagは0です。

一部の文字列の境界が間違っていることを読みましたが、それを修正する方法を見つけることができません。

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

エラーの説明

_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文字の部分文字列を作成するには十分ではありません。

ソリューション:

  1. 三項演算子を使用して長さを検証_?:_

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

    注:三項演算子(_?:_)は_if else_の短い式ですが、これは ステートメントではありません これは、アトミックステートメントとして発生できないことを意味しますINVALID割り当てがないため

    _((someString.length()>499) ? someString.substring(0,500):"Invalid length");
    _
  2. _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のサブクラスであることを意味します。これは、ある種の(配列、文字列、またはベクトルなどの)インデックスがList。を使用して範囲外です。

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

なぜこれらの例外が発生するのですか?

  • arraysまたはcharAtsubstring関数での負のインデックスの使用
  • BeginIndexが_0_より小さいか、endIndexが作成する入力文字列の長さより大きいsubstringまたはbeginIndexがendIndexより大きい
  • _endIndex - beginIndex_の結果が_0_より小さい場合
  • 入力文字列/配列が空の場合

INFO:適切な例外のオブジェクトを作成し、throwを使用して発生した場所に渡すことは、JVMの仕事ですキーワードのように、またはthrowキーワードを使用して手動で行うこともできます。

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

どうすれば修正できますか?

  1. StackTraceの分析
  2. Null、長さ、または有効なインデックスに対する入力文字列の検証
  3. デバッグまたはログの使用
  4. Generic Exception catchブロックの使用

1.)StackTraceの分析

この投稿の最初に示したように、スタックトレースは、発生した場所、発生した理由に関する最初のメッセージで必要な情報を提供するので、そのコードを追跡して必要な解決策を適用できます。

たとえば、理由StringIndexOutOfBoundsExceptionの場合は、_package name indicating your class file_を探して、その行に移動し、理由を念頭に置いて、ソリューションを適用します

ドキュメントで例外とその原因について調べれば、これは有利なスタートです。

2.)null、長さ、または有効なインデックスに対する入力文字列の検証

応答のような実際の入力がサーバー(またはエラーまたは何もない)からのものであるかユーザーがわからない場合の不確実性の場合は、予期しないケースをすべてカバーすることをお勧めします。テストの制限をプッシュしたいユーザーはほとんどいないと思いますinput!=null && input.length()>0を使用するか、インデックスの場合は、三項演算子または_if-else_境界チェック条件を使用できます

3.)デバッグまたはログの使用

プロジェクトにブレークポイントを追加することで、プロジェクトの実行環境をデバッグモードでテストできます。システムはそこで停止し、次のアクションを待機します。その間、変数の値やその他の詳細を確認できます。

ログはチェックポイントのようなものなので、コントロールがこのポイントを通過すると詳細が生成されます。基本的には、システムによって提供される情報メッセージであり、ユーザーはLogsメッセージまたはPrintlnメッセージを使用してログメッセージを書き込むこともできます。

4.)Generic Exception catchブロックの使用

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

その他の参考資料

NullPointerExceptionとは何ですか。どのように修正しますか?

13
Pavneet_Singh