charAtメソッドに例外処理をする - Exception(例外) - 萌えJava超入門
第十九章 Exception(例外)

charAtメソッドに例外処理をする

String.charAtメソッドの例外をキャッチしましょう。

目次




1.charAtメソッドに例外処理をする


Stringクラスの charAtメソッドに例外処理をしてみましょう。

この章の目標は、
例外をスローしてくるメソッドを
使えるようになることだ。
つまり charAtメソッドも
例外をスローしてくるのね。
そうなんだ。
その例外を
適切にキャッチしたい。

charAtメソッドは、引数に受けたインデックスの文字を返すメソッドです。
でも、引数にマイナスの値や、文字数以上の値が代入された場合、戻り値を返せません。
charAtメソッドの中はどうなっているのか、少し覗いてみましょう。

Stringクラスの
charAtメソッドのソースだ。
java.lang.Stringクラスの charAtメソッド抜粋
    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

メソッドがうまく処理できない場合に備えて、if文で分岐しています。
引数が不正な場合は、throwStringIndexOutOfBoundsException
をスローしています。
この時、charAtメソッドは処理を中断しているので、戻り値が返りません。



2.サンプル

charAtメソッドがスローする StringIndexOutOfBoundsException
キャッチします。
StringIndexOutOfBoundsException は非チェック例外なので、例外処理をしなくてもコンパイルエラーにはなりません。
ただ、実行して、StringIndexOutOfBoundsException がスローされた場合の処理を try-catch で明記しました。

例外をスローされた場合、そのままだと 変数 ch が未初期化の状態になってしまうので、
catchブロックの中で ch に代替え文字として '*' を代入しました。
強制終了しないで処理を完了します。

//Sample19_26.java
class Sample19_26{
    /* charAtメソッドが例外をスローすると
    変数 ch にアスタリスクを代入する例
    */
    public static void main(String[] args){
        String str = "ヒザカックン"; // 文字数 6
        int index = 6;
        char ch;
        final char ch0 = '*'; //代替え文字
        try{
            ch = str.charAt(index);
        }catch( StringIndexOutOfBoundsException e){
            e.printStackTrace();
            ch = ch0;
        }
        System.out.println("str[" + index + "] = [" + ch + "]");
    }
}


コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample19_26.java
ws>java Sample19_26
java.lang.StringIndexOutOfBoundsException: String index out of range: 6
        at java.lang.String.charAt(Unknown Source)
        at Sample19_26.main(Sample19_26.java:9)
str[6] = [*]


catch の中にも
普通に処理が書けるんすね。



これで例外にも
備えられるな。


3.スローされた例外の種類は情報源


蛇足的な実験です。
斜めに読んでくれ。
↓の charAtメソッドのグレーの部分ですが、ホントに必要なのでしょうか。
たとえグレーの部分が無くても、
value[index] で 範囲外のインデックスを参照した場合、
Java仮想マシンから「ArrayIndexOutOfBoundsException」がスローされます。

そう言われてみれば
そうっスね。
そう。
charAtメソッドは、
わざわざ例外の
種類を変えているんだ。
java.lang.Stringクラスの charAtメソッド抜粋
    public char charAt(int index) {
          if ((index < 0) || (index >= value.length)) {
              throw new StringIndexOutOfBoundsException(index);
          }
          return value[index];//ココで ArrayIndexOutOfBoundsException
    }

先ずはグレーの部分が無くても
ArrayIndexOutOfBoundsException を
スローすることを確認してみよう。
Stringクラスをいじるわけには行きませんので、
Stringクラスをニセたクラスを作って実験してみましょう。
サラリと小難しいコード
出してきたわね。
//Sample19_22.java
class Sample19_22{
    public static void main(String[] args){
        imitationString imiStr = new imitationString("ヒザカックン");

        try{
            System.out.println(imiStr.imitationCharAt(6));
            System.out.println("end of try.");
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println(e);//例外の表示
        }

        System.out.println("complete");
    }
}

class imitationString{
    /*
    * ニセStringクラス
    */
    final char[] value;

    /*コンストラクタ*/
    imitationString(String str){
        value = str.toCharArray();
    }

    /*ニセCharAtメソッド*/
    public char imitationCharAt(int index) {
        return value[index];//ココで ArrayIndexOutOfBoundsException
    }
}

やっぱり
グレーの部分が無ければ
ArrayIndexOutOfBoundsException が
スローされますね。
コマンドライン
ws>javac -encoding UTF-8 Sample19_22.java
ws>java Sample19_22
java.lang.ArrayIndexOutOfBoundsException: 6
complete


わざわざ例外の種類を変えているのは、 スローされる例外の種類が、例外が発生した原因の大きなヒントになるからです。
ArrayIndexOutOfBoundsException「範囲外の配列インデックスによる例外」 と、
StringIndexOutOfBoundsException「範囲外の文字列インデックスによる例外」。
直感的に文字列操作の問題を連想できるのは、やはり後者でしょう。

また、try-catchする際にも、ArrayIndexOutOfBoundsException とは別のcatchブロックで受けることもできます。

この if文はやさしさでできているのです。




お疲れ様でした。




© 2019 awasekagami