こんにちは、かつコーチです。
JavaのString(文字列を表すクラス)は、他のプリミティブ型と少し違う性質を持っています。
特に「比較の仕方」で初心者がほぼ必ずつまずくポイントがあります。
この記事では、Stringの作成・比較・連結について、実際のエラー例も交えて解説します。
Stringとは?
Stringはプリミティブ型ではなくクラス
intやbooleanはプリミティブ型でしたが、Stringはクラス(オブジェクトの設計図)であり、文字列はオブジェクトとして扱われます。
そのため、値そのものではなく「値への参照(メモリ上の場所)」を変数が保持しているという点が、他のプリミティブ型と根本的に異なります。
文字列リテラルと文字列プール
String name1 = "かつコーチ";
String name2 = "かつコーチ";
Javaは同じ内容の文字列リテラルを文字列プール(同じ内容の文字列を再利用する仕組み)で管理しています。
そのためname1とname2は実は同じオブジェクトを指しており、==で比較しても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("完了済みです");
}
statusがnullの状態で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, 初心者向け, 基本文法