1. ホーム
  2. java

[解決済み] StringIndexOutOfBoundsExceptionとは何ですか?どうすれば直せますか?

2022-03-13 08:39:30

質問

これは私のコードです。

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

アンドロイドのドキュメントから与えられたデフォルトです。私はURLだけを変更しました。

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

java.lang.StringIndexOutOfBoundsException: length=28; regionStart=1; リージョン長=499 at java.lang.String.substring(String.java:1931) 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)); のメッセージは届きますが、テキストビューは更新されず、アプリはクラッシュします。

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

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

traceTag は 0 です。

文字列の境界が一部おかしいという記事を読みましたが、修正方法がわかりません。

解決方法を教えてください。

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とは何ですか?

<ブロッククオート

IndexOutOfBoundsException のサブクラスです。 RuntimeException 平均 これはチェックされていない例外で、インデックスが ある種のもの(配列、文字列、ベクトルなど)が外れた場合。 の範囲外です。例えばListを使用します。

のように ドキュメンテーション

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 クラスと length の連想フィールドです。 array .

なぜこのような例外が発生するのですか?

  • ネガティブインデックスの使用方法 arrays または charAt , substring 機能
  • BeginIndexが 0 を作成するための入力文字列の長さより大きいか、またはendIndexを作成するための入力文字列の長さより大きい。 substring またはbeginIndexがendIndexより大きい。
  • いつ endIndex - beginIndex よりも小さい。 0
  • 入力文字列/配列が空の場合

INFO : JVMの仕事は、適切な例外のオブジェクトを作成し、その例外が発生した場所に throw のようなキーワードを使用するか、または、手動で throw というキーワードもあります。

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

どうすれば直せますか?

  1. スタックトレースの解析
  2. 入力文字列のnullity、length、valid indexの検証
  3. デバッグやログを利用する
  4. 汎用例外キャッチブロックの使用

1.) スタックトレースの解析

この記事の冒頭で示したように、スタックトレースは、それが発生した場所、それが発生した理由についての最初のメッセージで必要な情報を提供するので、あなたは単にそのコードをトレースし、必要な解決策を適用することができます。

例えば、以下のような理由です。 StringIndexOutOfBoundsException を探し、あなたの package name indicating your class file そして、その行に行き、その理由を心に留めて、単純に解決策を適用します。

例外とその原因についてもドキュメントで勉強しておくと、先が見えてきますよ。

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

サーバーからのレスポンス(あるいはエラーか何か)、ユーザーからのレスポンスなど、実際の入力が不明な場合は、想定外のケースをすべてカバーする方がよいでしょう。 でも、テストの限界に挑戦するのが好きなユーザーもいるはずです。 ということで input!=null && input.length()>0 を使うか、インデックスの場合は三項演算子や if-else バウンダリーチェック条件

3.) デバッグやログの活用

デバッグモードでプロジェクトの実行環境をテストするには、プロジェクトにブレークポイントを追加します。

ログはチェックポイントのようなもので、制御がこのポイントを通過すると詳細を生成します。基本的には、システムまたはユーザーによって与えられる情報メッセージで、LogsまたはPrintlnメッセージを使ってロギングメッセージを置くこともできます。

4.) 汎用例外キャッチブロックの使用

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とは何ですか、またどのように修正しますか?