これらの機能は文字データの処理でもよく使う機能で、どんな言語にも必ずといっていいほど備わっている機能なのだが、どうも使いづらいんですよね。
というのも、多くの言語ではこの種の機能で文字の位置を示す場合、"何文字目"という表現を使うのですが、Java の場合、"0から始まるインデックス"で表現するからなんです。
例えば、indexOf メソッドを使って
String str = new String( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
という文字列から 'G' の位置を取得する場合、
int idx = str.indexOf( 'G' );
というように記述しますが、このとき 'G' は7文字目だから 7 が返ってくるのかと思いきや 6 が返ってきます。
"0から始まるインデックス"なので"何文字目-1"で考えなければいけないのです。
※文字が見つからなかった場合は、-1 が返ってきます。
substring メソッドの場合はさらにややこしくなります。
上記の文字列から 'JKL' を取得したい場合、indexOf メソッドでの挙動を踏まえて、
String str2 = new String( str.substring( 9, 11 ) );
というように記述するとなぜか 'JK' が返ってくるのです。
substring メソッドの場合、第一引数には文字列の"開始位置のインデックス"を指定すればいいのですが、第二引数にはなぜか"終了位置のインデックス+1"を指定しなければならないのです。
つまり、上記の例の場合、
String str2 = new String( str.substring( 9, 12 ) );
とすると 'JKL' が返ってきます。
もっとも、substring メソッドのような機能の場合、"何文字目から何文字目まで"と指定する言語もあれば、"何文字目から何文字"と指定する言語もあり、インデックスうんぬんを抜きにしても混乱するのですが...
この"インデックスが0から始まる"という仕様、全ての情報を0と1で表現するコンピュータ的には好都合なのでしょうが、人間工学的にはかなりイケてません。
なんとかならないものでしょうか...