【Java】Java Stringの基本:作成・比較・連結の正しいやり方

Java

こんにちは、かつコーチです。

JavaのString(文字列を表すクラス)は、他のプリミティブ型と少し違う性質を持っています。
特に「比較の仕方」で初心者がほぼ必ずつまずくポイントがあります。
この記事では、Stringの作成・比較・連結について、実際のエラー例も交えて解説します。

Stringとは?

Stringはプリミティブ型ではなくクラス

intbooleanはプリミティブ型でしたが、Stringクラス(オブジェクトの設計図)であり、文字列はオブジェクトとして扱われます。
そのため、値そのものではなく「値への参照(メモリ上の場所)」を変数が保持しているという点が、他のプリミティブ型と根本的に異なります。

文字列リテラルと文字列プール

String name1 = "かつコーチ";
String name2 = "かつコーチ";

Javaは同じ内容の文字列リテラルを文字列プール(同じ内容の文字列を再利用する仕組み)で管理しています。
そのためname1name2は実は同じオブジェクトを指しており、==で比較してもtrueになります。
この仕組みが、後述する比較のつまずきポイントにつながります。

基本の書き方:作成と連結

Stringの作成方法

public class Main {
    public static void main(String[] args) {
        String greeting1 = "こんにちは"; // リテラルで作成(推奨)
        String greeting2 = new String("こんにちは"); // newで作成

        System.out.println(greeting1);
        System.out.println(greeting2);
    }
}

実務ではほとんどの場合、new String(...)ではなくリテラルでの作成を使います。
newを使うと文字列プールを使わず毎回新しいオブジェクトが生成されるため、無駄なメモリ消費につながります。

文字列の連結

String firstName = "太郎";
String lastName = "山田";
String fullName = lastName + firstName;
System.out.println(fullName); // 山田太郎

int age = 28;
String message = "年齢は" + age + "歳です";
System.out.println(message); // 年齢は28歳です

+演算子は数値との連結にも使え、自動で文字列に変換してくれます。
ただし大量の文字列を繰り返し連結する場合は、後述するStringBuilderを使う方が効率的です。

よくあるつまずきポイント・エラー対処

==で文字列比較してハマった一次情報

私が実際に初心者の頃、ユーザー入力と固定文字列を比較するコードで以下のようなバグを出しました。

❌ Before
import java.util.Scanner;

Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine(); // "yes"と入力

if (input == "yes") {
    System.out.println("承認しました");
} else {
    System.out.println("拒否しました"); // 想定外にこちらが実行される
}

"yes"と入力したにもかかわらず、常に「拒否しました」と表示されてしまいました。
Scannerから取得した文字列は文字列プールのリテラルとは異なるオブジェクトとして生成されるため、==で比較すると内容が同じでもfalseになります。

✅ After
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();

if (input.equals("yes")) {
    System.out.println("承認しました");
} else {
    System.out.println("拒否しました");
}

Stringの中身を比較したいときは、必ずequalsメソッドを使いましょう。
==は「同じオブジェクトかどうか」、equalsは「中身が同じかどうか」という違いを、このエラーをきっかけに強く意識するようになりました。

nullとの比較でNullPointerExceptionが発生する

❌ Before
String status = null;
if (status.equals("完了")) { // NullPointerException
    System.out.println("完了済みです");
}

statusnullの状態でequalsを呼び出すと、NullPointerExceptionが発生します。
nullという「何もない状態」に対してメソッドを呼び出すことはできません。

✅ After
String status = null;
if ("完了".equals(status)) {
    System.out.println("完了済みです");
}

比較対象がnullになる可能性があるときは、固定文字列を先に書いて.equals()を呼び出す書き方にすると、nullが来てもエラーになりません。
これは実務でもよく使われる防御的な書き方です。

応用・一歩先の使い方

大文字小文字を無視した比較とテキストブロック

String input = "YES";
System.out.println(input.equalsIgnoreCase("yes")); // true

String message = """
        こんにちは、かつコーチです。
        Java 21のテキストブロックを使うと
        改行を含む文字列も読みやすく書けます。
        """;
System.out.println(message);

equalsIgnoreCaseは大文字小文字を区別せずに比較したい場合に便利です。
また、Java 15以降で正式導入されたテキストブロック"""で囲む複数行の文字列リテラル)を使うと、改行やエスケープを気にせず長い文章を記述できます。
Java 21系では標準機能なので、複数行の文字列を扱うときにはぜひ活用してください。

まとめ

この記事のポイント

  • Stringはプリミティブ型ではなくクラスであり、文字列プールという仕組みで管理されている
  • 文字列の中身比較は==ではなく必ずequalsを使う
  • 比較対象がnullになりうる場合は、固定文字列側から.equals()を呼ぶと安全
  • Java 21のテキストブロックを使うと複数行の文字列を読みやすく書ける

次に読むべき記事

  • 演算子の基本(算術・比較・論理)
  • StringBuilderで文字列を効率よく組み立てる

タグ: Java, 初心者向け, 基本文法

タイトルとURLをコピーしました