Javaのsubstringで、後ろから(右から)文字列を切り取る方法、エラーを回避する方法、前から(左から)文字列を切り取る方法を紹介します。

■目次


使い方1 切り取りの開始位置だけ指定する方法

String s1 = "20140114";
String s2 = s1.substring(4);
yyyyMMdd形式の日付文字列から、月と日の部分を切り取るコードです。
このコードを動かすとString変数s2には「0114」が設定されます。

「s1.substring(4)」とすることで、s1の5文字目から末尾までの文字列を切り取って返してくれます。
「切り取る」と言っても、文字列s1の内容は変化しませんのでご注意を。

使い方2 開始位置と終了位置を指定する方法

次はyyyyMMdd形式の文字列から、月の部分だけを切り取ってみましょう。
String s1 = "20140114";
String s2 = s1.substring(4, 6);
最初のコードにパラメータが増えました。
「s1.substring(4, 6)」とすることで、s1の5文字目から6文字目までを切り取ってくれます。
「s1.substring(4, 6)」としているのに、「5文字目から」というのがピンと来ませんが、下の図のように考えるとなんとか納得できると思います。

使い方3 前から(左から)xx文字切り取る方法

String s1 = "20140114";
String s2 = s1.substring(0, 4);
「s1.substring(0, 4)」とすることでs1の先頭から4文字を切り取ってくれます。

使い方4 後ろから(右から)xx文字切り取る方法

Java以外の言語には「Right(s1, 3)」とすると文字列の後ろから3文字を切り取ってくれる関数があります。
Javaにはこのような関数がないので、必要な場合は自作するとよいです。

まずは、単純に文字列の後ろから3文字を切り取る方法です。
String s1 = "123456";
String s2 = null;
s2 = s1.substring(s1.length() - 3);
このように、対象の文字列の長さから切り取りたい文字数を引いた数を、substringのパラメータに渡すことで「後ろから3文字」を取得できるようになります。
ちなみに、このコードを実行するとs2に「456」が設定されます。

では、これをJavaのメソッドにしてみましょう。
public class StringUtil {
 public static String right(String s1, int idx) {
   if (s1 == null) {
     // s1がnullの場合、空の文字列を返す
     return "";
   }
   if (s1.length() <= idx) {
     // s1の文字数が指定文字数以下の場合、s1をそのまま返す
     return s1;
   }
   // null以外かつ、指定文字数より大きい場合、文字列の後ろから指定文字数を切り取る
   return s1.substring(s1.length() - idx);
 }
}
これは、パラメータの文字列s1の後ろから指定文字数を切り取って返すメソッドです。
s1がnullの場合は空文字を返し、s1が指定文字数以下の場合はs1をそのまま返すようになっています。

このメソッドを使う場合は以下のようにします。
String s1 = "123456";
String s2 = StringUtil.right(s1, 4);
今回は指定文字数を「4」としたので、s2には「3456」が設定されます。

使い方5 文字数が足りない場合の substring

次は「文字数が少ないケース」です。
String s1 = "20140";
String s2 = s1.substring(4, 6);
残念ながらこのコードを実行すると以下のようなエラーになります。
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 6
    at java.lang.String.substring(String.java:1934)
    at SubstringSample.main(SubstringSample.java:10)

String変数s1は5文字しかないのに、5~6文字目を要求するとエラーになってしまいます。
そんな時は、文字数を数えてから処理するようにしましょう。
String s1 = "20140";
String s2 = null;
if (s1.length() >= 6) {
  s2 = s1.substring(4, 6);
}
こんな風にif文とlengthメソッドの組み合わせで「String変数s1の文字数が6文字以上ならsubstringをする」このようにすればエラーを回避できます。

使い方6 String変数が null の場合の substring

次はString変数が null の場合です。
String s1 = null;
String s2 = s1.substring(4, 6);
このコードも文字数が足りない場合と同じように、以下のようなエラーになってしまいます。
Exception in thread "main" java.lang.NullPointerException
    at SubstringSample.main(SubstringSample.java:10)

使い方5でやった文字数を数える方法も、String変数が null の場合では効果がありません。
nullのオブジェクトに対しては、インスタンスメソッドはすべて「java.lang.NullPointerException」になってしまうからです。

それではString変数が null の場合を考慮した使い方です。
String s1 = null;
String s2 = null;
if (s1 != null) {
  s2 = s1.substring(4, 6);
}
String変数が null の場合は、上記のように「s1 != null」とやって、「String変数が null でない場合 substring を行う」とすればよいのです。
結果は null のままですが、これでエラーの発生は抑えられますし、s1にちゃんと日付文字列が設定されていれば、s2に月の部分の文字列が設定されます。

使い方7 変数が null の場合と文字数が足りない場合の substring

使い方5で文字数が足りない場合、6で変数が null の場合の substringの使い方を書きましたが、次は両方を考慮したコードです。
String s1 = null;
String s2 = null;
if (s1 != null && s1.length() >= 6) {
  s2 = s1.substring(4, 6);
}
これで、文字数が足りない場合と、変数が null の場合の両方に対応できます。
ポイントはnull判定のこの文「s1 != null」を先頭に持ってくることと、間に挟まっている「&&」です。
この書き方をすることで、「String変数s1がnullでなければ文字数の判定を行う」という動作をしてくれます。

ダメな書き方

if (s1.length() >= 6 && s1 != null) {
このように書くと、null判定の前に文字数判定を行ってしまい、NullPointerExceptionが発生します。

if (s1 != null & s1.length() >= 6) {
このように書くと、s1がnullでも文字数判定を行ってしまい、NullPointerExceptionが発生します。

添付ファイル