Edited at

java.lang.String#substringの心配事を調べた

More than 1 year has passed since last update.

記事の内容はJava8で検証しています。

※この記事が初投稿ですので至らないところがあればご容赦ください。


概要

substring()の引数の許容範囲がどうだったのか、とか、nullを返すことはあるのか、とかしばしば忘れるのでメモ。


まとめ


  • インデックスの適正範囲は0~文字列長(=.length())

  • インデックスに適正範囲外の値を与えると例外発生

  • substring()がnullを返すことはない

こういう記述をしても安心:

String src="abc|def";

String head=null,tail=null;

int p=src.indexOf('|');
if(p>0) {
head=src.substring(0,p); //ここが心配:p==0でもOK?
tail=src.substring(p+1); //ここが心配:p+1==src.length()でもOK?
}

//これも心配:nullを返すケースはある?
if(head==null) head=src;

...


メソッド

Stringから部分文字列を切り出して作った新たな文字列を返す。

二種類ある。


  • String substring(int beginIndex) …途中から末尾までを切り出す

  • String substring(int beginIndex, int endIndex) …中間を切り出す

中間を切り出す場合、beginIndexからendIndex の前まで(endIndex位置の文字は含まない)を切り出すことに注意。


文字位置

1文字単位。漢字とかのマルチバイト文字でも1文字単位。

先頭の文字位置は0。

末尾の文字位置は .length()-1 となる。

"abc".substring(1); //"bc"

"あいう".substring(1); //"いう"

…他の文字位置指定系メソッドと同様。


beginIndex:開始位置の範囲


適正範囲

0~文字列長(=.length())が適正範囲。

適正範囲終端は末尾文字位置(=length()-1)ではないことに注意。

"abc".substring(0); //"abc"

"abc".substring(2); //"c"
"abc".substring(3); //""(=空文字列。nullが返るわけではない)


適正範囲外の位置を指定した場合

例外発生。

"abc".substring(-2);

//java.lang.StringIndexOutOfBoundsException: String index out of range: -2

"abc".substring(4);
//java.lang.StringIndexOutOfBoundsException: String index out of range: -1

メッセージの数値には二種類の意味がある。


  • 文字位置<0の場合:「逸脱した文字位置」

  • 文字位置>文字列長の場合:「切り出そうとした文字列長」(=文字列長-開始位置)

デバッグ時にエラー出力の解釈で悩みそうなのでちょっと注意。


endIndex:末尾位置の範囲


適正範囲

開始位置と同様。

0~文字列長(=.length())が適正範囲。

適正範囲終端は末尾文字位置(=length()-1)ではないことに注意。

"abc".substring(0,0); //""(=空文字列。nullが返るわけではない)

"abc".substring(0,2); //"ab"
"abc".substring(0,3); //"abc"
"abc".substring(3,3); //""(=空文字列。nullが返るわけではない)


開始位置と末尾位置が同じ場合

空文字列が返る。

nullが返るわけではない。

"abc".substring(1,1); //""(=空文字列。nullが返るわけではない)


適正範囲外の値を指定した場合

例外発生。

"abc".substring(-1,4);

//java.lang.StringIndexOutOfBoundsException: String index out of range: -1

"abc".substring(0,4);
//java.lang.StringIndexOutOfBoundsException: String index out of range: 4

メッセージの数値には「逸脱した文字位置」が充てられる。

判定は開始位置→末尾位置の順に行われる。


開始位置と末尾位置が転倒している場合

例外発生。

"abc".substring(2,0);

//java.lang.StringIndexOutOfBoundsException: String index out of range: -2

メッセージの数値には「切り出そうとした文字列長」が充てられる。


substring()がnullを返すケース

ない。

Java8のソースで確認したところでは、newされたStringインスタンスか、自分自身が返される(文字列全体を返す場合)。

自分自身がnullの場合はそもそもメソッド呼び出しの時点でNullPointerExceptionが発生する。


おまけ:((String)null).substring()を実行した場合

当然、NullPointerException発生。

String n=null;

String s=n+""; //nullが"null"に変換される
n.substring(0); //NG:例外発生
s.substring(0); //OK:"null"

勘違いしそうなので要注意。