文字列切り取り関数である「substring」使用時のエラーの原因と回避方法のまとめです。
目次
java.lang.NullPointerException
NullPointerExceptionいわゆるヌルポが発生する場合、substringを仕掛けるオブジェクトが「null」(設定されていない)になっています。
例1:関数の戻り値が「null」
String s = getValue();
s = s.substring(1, 2);
「getValue」関数の戻り値が「null」の場合「NullPointerException」が発生します。
対策1-1:substringの直前にチェックを入れる
String s = getValue();
if (s != null) {
s = s.substring(1, 2);
}
「getValue」の戻り値がnullでない場合だけsubstringを行うようチェックを追加しました。
実際には「戻り値がnullだった場合にはどうすべきか」というのも考えなければいけません。
対策1-2:「getValue」関数の戻り値がnullにならないようにする
String getValue() {
String ret = null;
// ・・・関数の処理・・・
if (ret == null) {
return "retがnullの場合の値";
} else {
return ret;
}
}
「getValue」が戻り値を返すところにチェックを挿入し、戻り値がnullの場合規定の値を返却するよう修正しました。
「直前の関数がnullを返さない」と分かっていればsubstringの直前にnullチェックする必要はありません。
対策1-3:エラー処理を行う
try {
String s = getValue();
s = s.substring(1, 2);
} catch(Exception e) {
// ・・・エラー処理・・・
}
「getValue」の戻り値がnullだったらエラーになってOK、エラー処理をしてしまえ!という対策です。
この場合「nullチェックしてnullだったらエラーを投げる」の方がよいのかもしれません。
例2:if文の通り具合で「null」になる場合
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
}
s = s.substring(1, 2);
「getHanteiKekka」の戻り値がfalseの場合、「s」に値が設定されず「NullPointerException」が発生します。
対策2-1:すべてのif文のルートでもれなく値を設定する
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
s = "mogemoge";
}
s = s.substring(1, 2);
「判定結果がfalseの場合の処理」にも値を設定するように修正したので「NullPointerException」が発生しません。
今回の例ではif文のルートが2通りでしたが、if文が大量にあってルートを網羅しきれない場合はsubstringの直前でチェックするしかないでしょう。
対策2-2:substringの直前にチェックを入れる
対策1-1と同じなのでコードは省略します。
対策2-3:エラー処理を行う
対策1-3と同じなのでコードは省略します。
java.lang.StringIndexOutOfBoundsException: String index out of range: xxx
オブジェクトの文字数が足りない場合のエラーです。
対策は「NullPointerException」の対策に+αの形になります。
例1:関数の戻り値が短い
String s = getValue();
s = s.substring(1, 2);
この例では「getValue」関数の戻り値が0~1文字の場合「StringIndexOutOfBoundsException」が発生します。
2文字以上であれば例外は発生しません。
対策1-1:文字数チェックをする
String s = getValue();
if (s != null && s.length() >= 2) {
s = s.substring(1, 2);
}
「sがnull以外かつ2文字以上の場合」にsubstringを行うように修正しました。
nullチェックを入れているのは、sがnullだと「length」の方でエラーになる可能性があるためです。
対策1-2:「getValue」関数の戻り値が2文字以下にならないようにする
String getValue() {
String ret = null;
// ・・・関数の処理・・・
if (ret == null || ret.length() <= 1) {
return "retがnullまたは1文字以下の場合の値";
} else {
return ret;
}
}
こちらも「NullPointerException」の例に+αした内容ですが「戻り値がnullまたは1文字以下の場合」に規定の値を返すように修正してあります。
対策1-3:エラー処理を行う
try {
String s = getValue();
s = s.substring(1, 2);
} catch(Exception e) {
// ・・・エラー処理・・・
}
「getValue」の戻り値が1文字だったらエラーになってOK、エラー処理をしてしまえ!という対策です。
「NullPointerException」の例と同じです。
例2:if文の通り具合で文字数が不足する場合
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
s = "m";
}
s = s.substring(1, 2);
「getHanteiKekka」の戻り値がfalseの場合、「s」が1文字のため例外が発生します。
対策2-1:すべてのif文のルートで文字数が不足するしないように設定する
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
s = "mogemoge";
}
s = s.substring(1, 2);
「判定結果がfalseの場合の処理」にも値を設定するように修正したので例外が発生しません。
今回の例ではif文のルートが2通りでしたが、if文が大量にあってルートを網羅しきれない場合はsubstringの直前でチェックするしかないでしょう。
対策2-2:substringの直前にチェックを入れる
対策1-1と同じなのでコードは省略します。
対策2-3:エラー処理を行う
対策1-3と同じなのでコードは省略します。
例3:第2パラメータより第1パラメータの方が小さい
String s = getValue();
s = s.substring(2, 1);
これは「3文字目から1文字切り取り」という意図で記述しやすいコードです。
対策2-1:パラメータを適正な値に変更する
String s = getValue();
s = s.substring(2, 3);
「3文字目から1文字切り取り」の場合、パラメータは「2」と「3」が正解です。
これは気合で覚えるしかないです。
例4:第一パラメータが0未満の場合
String s = getValue();
int x = getKaishi();
int n = getMojisuu();
s = s.substring(x, x + n);
「xからn文字切り取り」という意図の使い方ですが「x」が0未満の場合にも例外が発生します。
パラメータを何らかの処理で決定している場合に発生しやすい例外です。
対策4-1:substringの直前にチェックを行う
String s = getValue();
int x = getKaishi();
int n = getMojisuu();
if (x >= 0) {
s = s.substring(x, x + n);
}
「x」が0以上の場合にだけsubstringを行うように修正しました。
第2パラメータが「x + n」ではなく「y」などの場合は第2パラメータも含めてチェックを行う必要があります。
対策4-2:0未満の値が設定されないようにする
int getKaishi() {
int ret = 0;
// ・・・getKaishiの処理・・・
if (ret < 0) {
return 0;
} else {
return ret;
}
}
「getKaishi」関数を修正し、戻り値に0未満の値が設定されないようにする対策です。
対策4-3:エラー処理を行う
対策1-3と同じなのでコードは省略します。
最終更新:2019年09月16日 16:49