こんにちは。「Javaを復習する初心者」です。
今回はString#charAt()メソッドを使ってみました。このメソッドはString型オブジェクトから特定の位置の一文字を取り出したい場合に使います。サンプルとして、先頭から一文字ずつ取り出すプログラムを書きました。ただし、今回はわざとエラーが起きるサンプルを作って、よくあるミスを挙げてみました。
ソースと実行結果
以下にフローを書きます。ただし、間違いが含まれます。
- String型変数sを定義し、”Hello World.”で初期化する。
- “全体:” + sをprintlnで出力する。
- 繰り返しカウンタiが0からs.length()以下まで以下の処理を繰り返す。
- (i + 1) + “番目:” + s.charAt(i)をprintlnで出力する。
以下はソースと実行結果です。
ソースコード
package stringTest;
public class HelloCharAt {
public static void main(String[] args) {
String s = "Hello World.";
System.out.println("全体:" + s);
for (int i = 0; i <= s.length() ; i++) {
System.out.println((i + 1) + "番目:" + s.charAt(i));
}
}
}
結果
全体:Hello World.
1番目:H
2番目:e
3番目:l
4番目:l
5番目:o
6番目:
7番目:W
8番目:o
9番目:r
10番目:l
11番目:d
12番目:.
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 12
at java.lang.String.charAt(String.java:658)
at stringTest.HelloCharAtAndLength.main(HelloCharAtAndLength.java:12)
解説
for文の繰り返しカウンタ変数iの値が12のとき、エラーが発生しました。StringIndexOutOfBoundsExceptionが発生したので、引数が範囲外であることが原因です。文字列は先頭一文字から順に0, 1, 2…と番号づけられています。参考書にも先頭が0と記載してあります。ちょっと気になったので以下にAPI仕様書を引用します。
- 修飾子と型
- char
- メソッドと説明
- charAt(int index)
指定されたインデックスのchar値を返します。
引数の名前がindexで説明に「インデックスのchar値」とありますので、配列と同じ考えで良いのでしょう。ここでさらに気になったのは、このcharAtというメソッドは内部でどのような処理をやっているのだろうということです。Eclipseのショートカット・キーを使って調べました。charAtのところにカーソルを合わせ、F3キーを押すと定義の箇所に移動します。
String.class
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
StringIndexOutOfBoundsExceptionをスローする条件でvalueという変数が登場します。このvalueはStrignクラスが持つフィールドの配列です。Stringオブジェクトが保持している文字列はこの変数に格納されるようです。条件式から、charAtに文字列の長さを入れるとエラーになります。retunrの箇所を見ると引数のindexをそのまま配列の要素番号に指定しています。これで文字列先頭は番号0で指定するということに納得がいきました。
もうひとつ、lengthメソッドの方はというとこれは単純にvalue.lengthを返却しています。indexが文字列の長さ以上の値の場合、エラーが発生するということです。