Javaでプログラミングを行っていると、文字列の特定の範囲を切り出したい場面が多々あります。

特に「ファイルパスから拡張子を取得する」「IDの末尾4桁を抽出する」といったように、文字列の後ろから指定した文字数を取得したいというニーズは非常に一般的です。

しかし、Javaの標準メソッドである substring は、開始位置をインデックス (0から始まる連番) で指定する仕様となっており、「後ろからn文字」という指定を直接行う引数は用意されていません。

そのため、文字列全体の長さを示す length() メソッドと組み合わせた計算が必要になります。

本記事では、Javaの substring メソッドを使用して、末尾から文字を抽出する具体的な方法を、初心者の方でも分かりやすくコード例とともに解説します。

例外処理や安全な実装方法についても触れていきますので、ぜひ参考にしてください。

Javaのsubstringメソッドの基本仕様

末尾からの抽出方法を学ぶ前に、まずは Java の java.lang.String クラスに用意されている substring メソッドの基本的な動作をおさらいしておきましょう。

このメソッドには、主に以下の2種類の使い方があります。

substring(int beginIndex)

この形式は、指定した 開始インデックスから文字列の最後まで を抽出します。

Javaのインデックスは 0 から始まるため、1文字目は 0、2文字目は 1 と数える点に注意してください。

substring(int beginIndex, int endIndex)

この形式は、開始位置と終了位置を範囲指定して抽出します。

ここで最も重要なルールは、終了インデックスで指定した位置の文字は含まれない ということです。

つまり、「開始位置以上、終了位置未満」の範囲が返されます。

後ろから指定文字数を抽出する論理

「後ろから n 文字取得する」という処理を実現するには、「(全体の長さ) – (取得したい文字数)」を計算し、その結果を開始インデックスとして渡すという考え方を用います。

例えば、”JavaProgramming” (15文字) という文字列から、後ろの3文字 “ing” を取り出したい場合を考えてみましょう。

  1. 文字列の長さ length() は 15 です。
  2. 取得したい文字数は 3 です。
  3. 開始インデックスは 15 - 3 = 12 となります。
  4. substring(12) を実行すると、インデックス 12, 13, 14 の文字が抽出されます。

このように、動的に文字列の長さを取得して計算することで、文字列の長さに依存せずに末尾抽出が可能になります。

実装例:末尾からn文字を取得する

それでは、実際にコードを書いてみましょう。

以下のプログラムは、標準的な末尾抽出のロジックを実装したものです。

Java
public class Main {
    public static void main(String[] args) {
        String text = "WelcomeToJavaWorld";
        int n = 5; // 抽出したい文字数

        // 文字列の長さを取得
        int length = text.length();

        // 後ろからn文字を抽出する計算
        // 開始位置 = 全体の長さ - n
        String result = text.substring(length - n);

        System.out.println("元の文字列: " + text);
        System.out.println("末尾から " + n + " 文字: " + result);
    }
}
実行結果
元の文字列: WelcomeToJavaWorld
末尾から 5 文字: World

このコードでは、text.length() が 18 を返し、そこから 5 を引いた 13 が substring の引数となります。

その結果、インデックス 13 から最後までの “World” が抽出されています。

例外を防ぐための安全な実装方法

先ほどの計算式 length() - n には注意点があります。

もし、変数 n (抽出したい文字数) が元の文字列の長さよりも大きい場合、計算結果がマイナスになってしまいます。

Javaの substring にマイナスの値を渡すと、StringIndexOutOfBoundsException という実行時エラーが発生します。

実務レベルのコードでは、以下のような 境界値のチェック を行うのが一般的です。

Java
public class SafeSubstring {
    public static void main(String[] args) {
        String input = "Java";
        int n = 10; // 文字列より長い文字数を指定

        String result;
        if (input == null) {
            result = "";
        } else if (input.length() <= n) {
            // 指定文字数が全体の長さ以上の場合は、文字列全体を返す
            result = input;
        } else {
            // 通常の末尾抽出
            result = input.substring(input.length() - n);
        }

        System.out.println("結果: " + result);
    }
}
実行結果
結果: Java

このように、if 文を使って条件分岐させることで、予期せぬクラッシュを防ぐことができます。

また、Math.max メソッドを利用して、インデックスが 0 を下回らないように制御するテクニックも有効です。

Java
int beginIndex = Math.max(0, input.length() - n);
String result = input.substring(beginIndex);

実践的なユースケース

「後ろから抽出」がよく使われる具体的なシナリオを見ていきましょう。

1. ファイルの拡張子を取得する

ファイル名から、最後のドット . 以降の文字列を取得する場合です。

この場合は、後ろから固定文字数ではなく、lastIndexOf と組み合わせて動的に位置を特定します。

Java
public class ExtensionCheck {
    public static void main(String[] args) {
        String filename = "document.pdf";
        int lastDotIndex = filename.lastIndexOf(".");

        if (lastDotIndex != -1) {
            // ドットの次の文字から最後までを抽出
            String extension = filename.substring(lastDotIndex + 1);
            System.out.println("拡張子: " + extension);
        }
    }
}

2. クレジットカード番号などのマスキング処理

セキュリティの観点から、下4桁だけを表示し、それ以外をアスタリスクで隠すような処理です。

Java
public class Masking {
    public static void main(String[] args) {
        String cardNumber = "1234-5678-9012-3456";
        int visibleCount = 4;

        if (cardNumber.length() > visibleCount) {
            String lastFour = cardNumber.substring(cardNumber.length() - visibleCount);
            System.out.println("表示用: ****-****-****-" + lastFour);
        }
    }
}

便利なライブラリの活用 (Apache Commons Lang)

もしプロジェクトで Apache Commons Lang という外部ライブラリが利用可能な場合、StringUtils クラスを使うことでより簡潔に記述できます。

StringUtils.right(String str, int len) というメソッドを使えば、内部で自動的にヌルチェックや長さのチェックを行ってくれるため、コードの可読性が大幅に向上します。

Java
// Apache Commons Lang を使用する場合
String result = StringUtils.right("JavaProgramming", 3); // "ing" が返る

自前で長さを計算する必要がないため、書き間違いによるバグを減らすことができます。

小規模な学習用プログラムであれば標準の substring で十分ですが、大規模な業務システムではこうしたライブラリの活用も検討に値します。

substring使用時のメモリに関する注意点

Javaの古いバージョン (Java 6以前) では、substring で生成された新しい文字列が、元の巨大な文字列の内部配列を共有し続けるという仕様がありました。

これにより、短い文字列を切り出したつもりでも、元の大きな文字列がメモリ上に残り続け、メモリリークの原因になることがありました。

現在の Java (Java 7 update 6 以降) では、substring新しい文字配列をコピーして生成する仕様 に変更されているため、このようなメモリ問題は基本的に解消されています。

安心して末尾抽出を利用してください。

まとめ

Javaで文字列を後ろから抽出するには、substring メソッドと length() メソッドを組み合わせるのが基本です。

基本公式

str.substring(str.length() - n)

注意点

指定する文字数が元の文字列長を超えるとエラーになる。

安全策

if 文や Math.max を使用してインデックスの範囲をチェックする。

文字列操作は、プログラミングにおいて避けては通れない基本中の基本です。

特に末尾からの抽出は、データのパースやフォーマット整形などで頻繁に登場します。

この機会に、インデックス計算の考え方をしっかりとマスターしておきましょう。

最後に、コードの可読性を高めるためには、単にメソッドを呼び出すだけでなく、nbeginIndex といった変数に適切な名前を付け、何のための計算なのかを明確にすることも忘れないでください。