「Java/substring使用時のエラーと回避方法」の編集履歴(バックアップ)一覧はこちら
追加された行は緑色になります。
削除された行は赤色になります。
文字列切り取り関数である「substring」使用時のエラーの原因と回避方法のまとめです。
* 目次
#contents(,fromhere=true)
* java.lang.NullPointerException
NullPointerExceptionいわゆるヌルポが発生する場合、substringを仕掛けるオブジェクトが「null」つまり空っぽになっています。
** 例1:関数の戻り値が「null」
#highlight() {{
String s = getValue();
s = s.substring(1, 2);
}}
「getValue」関数の戻り値が「null」の場合「NullPointerException」が発生します。
*** 対策1-1:substringの直前にチェックを入れる
#highlight() {{
String s = getValue();
if (s != null) {
s = s.substring(1, 2);
}
}}
「getValue」の戻り値がnullでない場合だけsubstringを行うように対策しました。
*** 対策1-2:「getValue」関数の戻り値がnullにならないようにする
#highlight() {{
String getValue() {
String ret = null;
// ・・・関数の処理・・・
if (ret == null) {
return "retがnullの場合の値";
} else {
return ret;
}
}
}}
「getValue」が戻り値を返すところにチェックを挿入し、戻り値がnullの場合規定の値を返却するよう策しました。
** 例2:if文の通り具合で「null」になる場合
#highlight() {{
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
}
s = s.substring(1, 2);
}}
「getHanteiKekka」の戻り値がfalseの場合、「s」に値が設定されず「NullPointerException」が発生します。
*** 対策2-1:すべてのif文のルートでもれなく値を設定する
#highlight() {{
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
s = "mogemoge";
}
s = s.substring(1, 2);
}}
「判定結果がfalseの場合の処理」にも値を設定するように修正したので「NullPointerException」が発生しません。
*** 対策2-1:substringの直前にチェックを入れる
対策1-1と同じなのでコードは省略します。
文字列切り取り関数である「substring」使用時のエラーの原因と回避方法のまとめです。
* 目次
#contents(,fromhere=true)
* java.lang.NullPointerException
NullPointerExceptionいわゆるヌルポが発生する場合、substringを仕掛けるオブジェクトが「null」(設定されていない)になっています。
** 例1:関数の戻り値が「null」
#highlight() {{
String s = getValue();
s = s.substring(1, 2);
}}
「getValue」関数の戻り値が「null」の場合「NullPointerException」が発生します。
*** 対策1-1:substringの直前にチェックを入れる
#highlight() {{
String s = getValue();
if (s != null) {
s = s.substring(1, 2);
}
}}
「getValue」の戻り値がnullでない場合だけsubstringを行うようチェックを追加しました。
実際には「戻り値がnullだった場合にはどうすべきか」というのも考えなければいけません。
*** 対策1-2:「getValue」関数の戻り値がnullにならないようにする
#highlight() {{
String getValue() {
String ret = null;
// ・・・関数の処理・・・
if (ret == null) {
return "retがnullの場合の値";
} else {
return ret;
}
}
}}
「getValue」が戻り値を返すところにチェックを挿入し、戻り値がnullの場合規定の値を返却するよう修正しました。
「直前の関数がnullを返さない」と分かっていればsubstringの直前にnullチェックする必要はありません。
*** 対策1-3:エラー処理を行う
#highlight() {{
try {
String s = getValue();
s = s.substring(1, 2);
} catch(Exception e) {
// ・・・エラー処理・・・
}
}}
「getValue」の戻り値がnullだったらエラーになってOK、エラー処理をしてしまえ!という対策です。
この場合「nullチェックしてnullだったらエラーを投げる」の方がよいのかもしれません。
** 例2:if文の通り具合で「null」になる場合
#highlight() {{
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
}
s = s.substring(1, 2);
}}
「getHanteiKekka」の戻り値がfalseの場合、「s」に値が設定されず「NullPointerException」が発生します。
*** 対策2-1:すべてのif文のルートでもれなく値を設定する
#highlight() {{
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:関数の戻り値が短い
#highlight() {{
String s = getValue();
s = s.substring(1, 2);
}}
この例では「getValue」関数の戻り値が0~1文字の場合「StringIndexOutOfBoundsException」が発生します。
2文字以上であれば例外は発生しません。
*** 対策1-1:文字数チェックをする
#highlight() {{
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文字以下にならないようにする
#highlight() {{
String getValue() {
String ret = null;
// ・・・関数の処理・・・
if (ret == null || ret.length() <= 1) {
return "retがnullまたは1文字以下の場合の値";
} else {
return ret;
}
}
}}
こちらも「NullPointerException」の例に+αした内容ですが「戻り値がnullまたは1文字以下の場合」に規定の値を返すように修正してあります。
*** 対策1-3:エラー処理を行う
#highlight() {{
try {
String s = getValue();
s = s.substring(1, 2);
} catch(Exception e) {
// ・・・エラー処理・・・
}
}}
「getValue」の戻り値が1文字だったらエラーになってOK、エラー処理をしてしまえ!という対策です。
「NullPointerException」の例と同じです。
** 例2:if文の通り具合で文字数が不足する場合
#highlight() {{
String s = null;
if (getHanteiKekka()) {
// ・・・判定結果がtrueの場合の処理・・・
s = "hogehoge";
} else {
// ・・・判定結果がfalseの場合の処理・・・
s = "m";
}
s = s.substring(1, 2);
}}
「getHanteiKekka」の戻り値がfalseの場合、「s」が1文字のため例外が発生します。
*** 対策2-1:すべてのif文のルートで文字数が不足するしないように設定する
#highlight() {{
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パラメータの方が小さい
#highlight() {{
String s = getValue();
s = s.substring(2, 1);
}}
これは「3文字目から1文字切り取り」という意図で記述しやすいコードです。
*** 対策2-1:パラメータを適正な値に変更する
#highlight() {{
String s = getValue();
s = s.substring(2, 3);
}}
「3文字目から1文字切り取り」の場合、パラメータは「2」と「3」が正解です。
これは気合で覚えるしかないです。
** 例4:第一パラメータが0未満の場合
#highlight() {{
String s = getValue();
int x = getKaishi();
int n = getMojisuu();
s = s.substring(x, x + n);
}}
「xからn文字切り取り」という意図の使い方ですが「x」が0未満の場合にも例外が発生します。
パラメータを何らかの処理で決定している場合に発生しやすい例外です。
*** 対策4-1:substringの直前にチェックを行う
#highlight() {{
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未満の値が設定されないようにする
#highlight() {{
int getKaishi() {
int ret = 0;
// ・・・getKaishiの処理・・・
if (ret < 0) {
return 0;
} else {
return ret;
}
}
}}
「getKaishi」関数を修正し、戻り値に0未満の値が設定されないようにする対策です。
*** 対策4-3:エラー処理を行う
対策1-3と同じなのでコードは省略します。