Javaの文字列の空判定とは、変数の中身が「null」「空文字」「空白だけ」のどれかに当たるかを調べる処理です。 長さが0かどうかだけを見るのが isEmpty()、空白だけの文字列も空とみなすのが isBlank()(Java 11以降)で、どちらも変数が null のときは例外になります。そのため、null を先に調べる s == null || s.isBlank() が基本の形になります。

この記事では、null・空文字・半角空白・全角空白・タブ・改行の6種類の入力を、6通りの判定方法に通した結果を1枚の早見表にしました。表の値はすべて OpenJDK 21.0.10 で実際に動かした出力です。あわせて、null で止まる様子の再現と、Java 11以降用・Java 8用の定型コードをコピーできる形で載せています。

文字列の空判定の早見表

下の表は、この記事の「早見表を作ったコードと実行結果」で動かした出力をまとめたものです。true は「空と判定された」、false は「空ではないと判定された」、例外は NullPointerException で止まったことを表します。

入力 s.isEmpty() s.isBlank() s.trim().isEmpty() s.strip().isEmpty() StringUtils.isEmpty(s) StringUtils.isBlank(s)
null 例外 例外 例外 例外 true true
空文字 "" true true true true true true
半角空白 " " false true true true false true
全角空白 " " false true false true false true
タブ "\t" false true true true false true
改行 "\n" false true true true false true
文字あり " a " false false false false false false

表から読み取れる要点は3つです。

  • String のメソッド4つは、null を渡すとすべて例外になります。 null でも結果が返るのは StringUtils(Apache Commons Lang)の2つだけです。
  • 全角空白を空と判定しないのは trim().isEmpty() だけです。日本語の入力を扱うなら isBlank() か strip().isEmpty() が合います。
  • isEmpty() は空白を文字として数えるので、半角空白1つでも false になります。

やりたいことから選ぶときは、次の表を使ってください。

やりたいこと Java 11以降 Java 8
null と空文字を空とみなす s == null || s.isEmpty() 同じ
null・空文字・空白だけを空とみなす s == null || s.isBlank() 1文字ずつ Character.isWhitespace で調べる(後述)
ライブラリで1行にしたい StringUtils.isBlank(s) 同じ
前後の空白を取り除く s.strip() s.trim()(全角空白は残る)
空白だけの入力を null にそろえる s.isBlank() ? null : s.strip() 自作メソッドで判定

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Java文字列の空判定|isEmptyとisBlankの違い早見表」

null・空文字・空白の違いを整理する

空判定で迷いやすいのは、「空」という言葉が3つの状態を指しているからです。まず3つを別のものとして区別すると、どのメソッドを使うかが決めやすくなります。

状態 コード上の書き方 意味 length()
null String s = null; 変数がどの文字列も指していない 呼ぶと例外
空文字 String s = ""; 文字列はあるが、長さが0 0
空白だけ String s = " "; 空白文字が1つ以上入っている 1以上

null は「文字列がない」状態で、空文字は「長さ0の文字列がある」状態です。null の変数に対して s.isEmpty() のようにメソッドを呼ぶと、呼び出す相手がいないので NullPointerException が発生します。空文字や空白だけの文字列は、文字列そのものは存在するので、メソッドを呼んでも例外にはなりません。

画面の入力欄やCSVファイルから受け取る値は、この3つのどれにもなり得ます。たとえば入力欄を何も触らずに送信すると空文字、スペースキーを押しただけなら空白だけ、項目そのものが送られてこなければ null、という具合です。受け取った値を使う前に、3つをまとめて調べる形にしておくと扱いやすくなります。

isEmptyとisBlankの違い

2つのメソッドの違いは、空白だけの文字列をどう扱うかです。

項目 isEmpty() isBlank()
true になる条件 長さが0 長さが0、またはすべて空白文字
使えるバージョン Java 6以降 Java 11以降
半角空白・タブ・改行 false true
全角空白 false true
null のとき NullPointerException NullPointerException
向いている用途 「1文字も入っていない」を調べる 「意味のある文字が入っていない」を調べる

Java 21 の公式APIドキュメント(String クラス)を開いて確認したところ、isEmpty() は「length() が 0 のときだけ true」、isBlank() は「空、または空白のコードポイントだけを含むとき true」と説明されています。ここでいう空白は Character.isWhitespace が true を返す文字で、半角空白・タブ・改行に加えて全角空白(U+3000)も含まれます。

isBlank() が Java 11 で加わったメソッドであることは、Java 8 向けにコンパイルして確かめました。次のコードを javac --release 8 でコンパイルします。

public class Java8Error {
    public static void main(String[] args) {
        String s = " ";
        System.out.println(s.isBlank());
    }
}

実行結果(javac --release 8 Java8Error.java、JDK 21.0.10):

Java8Error.java:4: error: cannot find symbol
        System.out.println(s.isBlank());
                            ^
  symbol:   method isBlank()
  location: variable s of type String
1 error

Java 8 では isBlank() が見つからず、コンパイルエラーになります。 Java 8 で動かすコードでは、後半の「Java 8用の定型コード」を使ってください。

入力チェックではどちらを選ぶか

人が入力した値を調べるなら isBlank()、プログラムが作った値を調べるなら isEmpty() と考えると選びやすくなります。

場面 選ぶメソッド 理由
名前・件名などの必須入力 isBlank() 空白だけの入力を未入力として扱える
検索キーワードが入っているか isBlank() 空白だけで検索が走るのを防げる
区切り文字で分割した結果の空要素 isEmpty() 空白も値として残したい場合がある
パスワードなど空白も意味を持つ値 isEmpty() 空白を文字として数える必要がある
設定値が未設定かどうか isBlank() 設定ファイルの行末の空白を無視できる

早見表を作ったコードと実行結果

冒頭の早見表は、次のコードの出力から作りました。StringUtils は Apache Commons Lang のクラスで、手元では apt で入る commons-lang3 3.14.0 の jar をクラスパスに指定しています。

import org.apache.commons.lang3.StringUtils;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Predicate;

public class EmptyTable {
    // 判定を実行し、NullPointerException なら "NPE" と表示する
    static String run(Predicate<String> p, String s) {
        try {
            return String.valueOf(p.test(s));
        } catch (NullPointerException e) {
            return "NPE";
        }
    }

    public static void main(String[] args) {
        Map<String, String> inputs = new LinkedHashMap<>();
        inputs.put("null", null);
        inputs.put("空文字", "");
        inputs.put("半角空白", " ");
        inputs.put("全角空白", " ");
        inputs.put("タブ", "\t");
        inputs.put("改行", "\n");
        inputs.put("文字あり", " a ");

        System.out.println("入力 | isEmpty | isBlank | trim().isEmpty | strip().isEmpty"
                + " | StringUtils.isEmpty | StringUtils.isBlank");
        for (Map.Entry<String, String> e : inputs.entrySet()) {
            String s = e.getValue();
            System.out.println(e.getKey()
                    + " | " + run(String::isEmpty, s)
                    + " | " + run(String::isBlank, s)
                    + " | " + run(x -> x.trim().isEmpty(), s)
                    + " | " + run(x -> x.strip().isEmpty(), s)
                    + " | " + StringUtils.isEmpty(s)
                    + " | " + StringUtils.isBlank(s));
        }
    }
}

実行コマンドと実行結果(OpenJDK 21.0.10、commons-lang3 3.14.0):

$ java -cp /usr/share/java/commons-lang3-3.14.0.jar EmptyTable.java
入力 | isEmpty | isBlank | trim().isEmpty | strip().isEmpty | StringUtils.isEmpty | StringUtils.isBlank
null | NPE | NPE | NPE | NPE | true | true
空文字 | true | true | true | true | true | true
半角空白 | false | true | true | true | false | true
全角空白 | false | true | false | true | false | true
タブ | false | true | true | true | false | true
改行 | false | true | true | true | false | true
文字あり | false | false | false | false | false | false

NPE は NullPointerException で止まったことを表します。null の行は String のメソッドがすべて NPE、全角空白の行は trim().isEmpty だけが false になっているのが、この表のいちばん大事なところです。

StringUtils を使うには、Maven なら org.apache.commons:commons-lang3 を依存関係に加えます。最新のバージョン番号は今回確認していないため、導入時に公式サイトで確かめてください。ライブラリを追加しない場合は、次の章の定型コードで同じ判定ができます。

nullでNullPointerExceptionになる例を再現する

null の変数に isEmpty() を呼ぶと、どのような表示で止まるのかを確認します。

public class Npe {
    public static void main(String[] args) {
        String name = null;
        if (name.isEmpty()) {
            System.out.println("空です");
        }
    }
}

実行結果(java Npe.java):

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "<local1>" is null
    at Npe.main(Npe.java:4)

メッセージの Cannot invoke "String.isEmpty()" は「String.isEmpty() を呼び出せません」、because ... is null は「〜が null だからです」という意味です。at Npe.main(Npe.java:4) の「4」が、例外の起きた行番号です。

"<local1>" は「1番目のローカル変数」という意味で、変数名の情報を含めずにコンパイルしたときの表示です。javac -g でデバッグ情報つきでコンパイルしてから実行すると、変数名がそのまま表示されました。

$ javac -g Npe.java
$ java Npe
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "name" is null
    at Npe.main(Npe.java:4)

メッセージに変数名が出ると、どの変数が null だったのかを行番号とあわせてすぐ特定できます。 Maven や Gradle でビルドする場合の既定の設定については、今回は未実行です。

条件の順番で結果が変わる

null チェックと isBlank() を組み合わせるときは、null を調べる式を左側に書きます。 || は左側が true なら右側を実行しない演算子なので、null のときに isBlank() が呼ばれずに済みます。

public class Order {
    public static void main(String[] args) {
        String s = null;

        // 直した後:null を先に調べる
        if (s == null || s.isBlank()) {
            System.out.println("OK: null を先に調べると止まらない");
        }

        // 直す前:isBlank() を先に書くと、null のとき例外になる
        try {
            if (s.isBlank() || s == null) {
                System.out.println("ここには来ない");
            }
        } catch (NullPointerException e) {
            System.out.println("順番が逆: NullPointerException");
        }

        // | が1本だと右側も必ず実行されるので、例外になる
        try {
            if (s == null | s.isBlank()) {
                System.out.println("ここには来ない");
            }
        } catch (NullPointerException e) {
            System.out.println("| が1本: NullPointerException");
        }
    }
}

実行結果:

OK: null を先に調べると止まらない
順番が逆: NullPointerException
| が1本: NullPointerException
書き方 s が null のとき 理由
s == null || s.isBlank() true が返る 左が true なので右を実行しない
s.isBlank() || s == null 例外 先に isBlank() が呼ばれる
s == null | s.isBlank() 例外 縦棒1本は両側を必ず実行する

「空ではない」ことを調べる場合は、s != null && !s.isBlank() と書きます。&& も左側が false なら右側を実行しないので、null のときに止まりません。

nullでも止まらない定型コード(Java 11以降)

Java 11以降では、次の2つのメソッドを用意しておくと、ほとんどの空判定をまかなえます。 そのままコピーして、共通のユーティリティクラスに置いて使えます。

public class SafeJava11 {
    // null・空文字・空白だけ(全角空白・タブ・改行を含む)を「空」とみなす
    static boolean isBlank(String s) {
        return s == null || s.isBlank();
    }

    // null と空文字だけを「空」とみなす(空白は文字として扱う)
    static boolean isEmpty(String s) {
        return s == null || s.isEmpty();
    }

    public static void main(String[] args) {
        String[] labels = {"null", "空文字", "半角空白", "全角空白", "タブ", "改行", "文字あり"};
        String[] inputs = {null, "", " ", " ", "\t", "\n", " a "};
        for (int i = 0; i < inputs.length; i++) {
            System.out.println(labels[i] + ": isEmpty=" + isEmpty(inputs[i])
                    + " / isBlank=" + isBlank(inputs[i]));
        }
    }
}

実行結果(OpenJDK 21.0.10):

null: isEmpty=true / isBlank=true
空文字: isEmpty=true / isBlank=true
半角空白: isEmpty=false / isBlank=true
全角空白: isEmpty=false / isBlank=true
タブ: isEmpty=false / isBlank=true
改行: isEmpty=false / isBlank=true
文字あり: isEmpty=false / isBlank=false

isBlank(s) の結果は、早見表の StringUtils.isBlank(s) の列と同じになっています。ライブラリを追加しなくても、同じ判定を1行で書けることがわかります。

入力チェックに組み込む例

受け取った名前が空なら案内文を返し、入っていれば前後の空白を取り除いて使う例です。

public class Guard {
    static String greet(String name) {
        // null を先に調べる。|| は左が true なら右を実行しない
        if (name == null || name.isBlank()) {
            return "名前が入力されていません";
        }
        return "こんにちは、" + name.strip() + "さん";
    }

    public static void main(String[] args) {
        System.out.println(greet(null));
        System.out.println(greet(""));
        System.out.println(greet(" "));
        System.out.println(greet(" 佐藤 "));
    }
}

実行結果:

名前が入力されていません
名前が入力されていません
名前が入力されていません
こんにちは、佐藤さん

3つ目の入力は全角空白1文字です。isBlank() を使っているので、全角空白だけの入力も未入力として扱えています。 4つ目は前後の半角空白を strip() で取り除いてから表示しています。

空白だけの入力をnullや初期値にそろえる

データベースに保存する前や、画面に表示する前に、空の値を1つの形にそろえておくと後の処理が単純になります。

public class Normalize {
    // null・空白だけの入力を null にそろえる(データベースに保存する前など)
    static String blankToNull(String s) {
        return (s == null || s.isBlank()) ? null : s.strip();
    }

    // null・空白だけの入力を初期値に置き換える
    static String defaultIfBlank(String s, String defaultValue) {
        return (s == null || s.isBlank()) ? defaultValue : s.strip();
    }

    public static void main(String[] args) {
        System.out.println("[" + blankToNull(" ") + "]");
        System.out.println("[" + blankToNull(" 備品A ") + "]");
        System.out.println("[" + defaultIfBlank(null, "未設定") + "]");
        System.out.println("[" + defaultIfBlank("\t", "未設定") + "]");
        System.out.println("[" + defaultIfBlank(" 会議室 ", "未設定") + "]");
    }
}

実行結果:

[null]
[備品A]
[未設定]
[未設定]
[会議室]

空の表し方を「null にそろえる」「空文字にそろえる」のどちらかに決めておくと、判定する側のコードが1通りで済みます。 チームで方針を1つに決めて、入口でそろえる形がおすすめです。

nullでも止まらない定型コード(Java 8)

Java 8 には isBlank() と strip() がないため、Character.isWhitespace で1文字ずつ調べるメソッドを用意します。

public class SafeJava8 {
    // Java 8 用:isBlank() の代わりに、1文字ずつ空白かどうかを調べる
    static boolean isBlank(String s) {
        if (s == null) {
            return true;
        }
        for (int i = 0; i < s.length(); i++) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    // null と空文字だけを「空」とみなす(isEmpty() は Java 6 から使える)
    static boolean isEmpty(String s) {
        return s == null || s.isEmpty();
    }

    public static void main(String[] args) {
        String[] labels = {"null", "空文字", "半角空白", "全角空白", "タブ", "改行", "文字あり"};
        String[] inputs = {null, "", " ", " ", "\t", "\n", " a "};
        for (int i = 0; i < inputs.length; i++) {
            System.out.println(labels[i] + ": isEmpty=" + isEmpty(inputs[i])
                    + " / isBlank=" + isBlank(inputs[i]));
        }
    }
}

javac --release 8 でコンパイルし、JDK 21 上で実行した結果です。Java 8 の実行環境そのものでは未実行です。

$ javac --release 8 SafeJava8.java
$ java SafeJava8
null: isEmpty=true / isBlank=true
空文字: isEmpty=true / isBlank=true
半角空白: isEmpty=false / isBlank=true
全角空白: isEmpty=false / isBlank=true
タブ: isEmpty=false / isBlank=true
改行: isEmpty=false / isBlank=true
文字あり: isEmpty=false / isBlank=false

Java 11以降用のコードと同じ結果になり、全角空白も空と判定できています。 Character.isWhitespace は isBlank() が内部の基準にしているメソッドと同じなので、判定のずれが起きません。

Java 8 でよく見かける s == null || s.trim().isEmpty() という書き方は、半角空白・タブ・改行には対応できますが、早見表のとおり全角空白だけの入力を空と判定しません。日本語の入力を扱うなら、上の isBlank メソッドのほうが合います。

Java 8 での書き方 半角空白 全角空白 null
s == null || s.isEmpty() 空としない 空としない 空とする
s == null || s.trim().isEmpty() 空とする 空としない 空とする
上の自作 isBlank(s) 空とする 空とする 空とする
StringUtils.isBlank(s) 空とする 空とする 空とする

trimとstripの違いと全角空白

trim() と strip() はどちらも前後の空白を取り除くメソッドですが、「空白」とみなす文字の範囲が違います。

項目 trim() strip()
使えるバージョン 初期のJavaから Java 11以降
取り除く文字 コードポイントが U+0020 以下の文字 Character.isWhitespace が true の文字
半角空白・タブ・改行 取り除く 取り除く
全角空白(U+3000) 残る 取り除く
片側だけ取り除く なし stripLeading()、stripTrailing()

取り除く文字の定義は、Java 21 の公式APIドキュメント(String クラス)を開いて確認した内容です。実際に動かして違いを見てみます。

public class TrimStrip {
    public static void main(String[] args) {
        String half = "  山田  ";      // 前後に半角空白
        String full = " 山田 ";      // 前後に全角空白

        System.out.println("trim  半角: [" + half.trim() + "] 長さ " + half.trim().length());
        System.out.println("strip 半角: [" + half.strip() + "] 長さ " + half.strip().length());
        System.out.println("trim  全角: [" + full.trim() + "] 長さ " + full.trim().length());
        System.out.println("strip 全角: [" + full.strip() + "] 長さ " + full.strip().length());

        String onlyFull = " ";        // 全角空白1文字だけ
        System.out.println("全角空白だけ trim().isEmpty()  = " + onlyFull.trim().isEmpty());
        System.out.println("全角空白だけ strip().isEmpty() = " + onlyFull.strip().isEmpty());
        System.out.println("全角空白だけ isBlank()         = " + onlyFull.isBlank());
    }
}

実行結果:

trim  半角: [山田] 長さ 2
strip 半角: [山田] 長さ 2
trim  全角: [ 山田 ] 長さ 4
strip 全角: [山田] 長さ 2
全角空白だけ trim().isEmpty()  = false
全角空白だけ strip().isEmpty() = true
全角空白だけ isBlank()         = true

trim() は全角空白を残すので、長さが4のままです。 全角空白だけの文字列に対して trim().isEmpty() が false になるのも、同じ理由です。Java 11以降で新しく書くコードでは、strip() と isBlank() を選ぶと全角空白もまとめて扱えます。

isBlankでも空と判定されない文字

isBlank() が空白とみなすのは Character.isWhitespace が true の文字です。見た目は空白でも、この基準に入らない文字があります。

public class Special {
    public static void main(String[] args) {
        String nbsp = String.valueOf((char) 0x00A0);   // ノーブレークスペース
        String zwsp = String.valueOf((char) 0x200B);   // ゼロ幅スペース
        String ctrl = String.valueOf((char) 0x0001);   // 制御文字

        System.out.println("NBSP     isBlank=" + nbsp.isBlank() + " / trim().isEmpty=" + nbsp.trim().isEmpty());
        System.out.println("ゼロ幅   isBlank=" + zwsp.isBlank() + " / trim().isEmpty=" + zwsp.trim().isEmpty());
        System.out.println("制御文字 isBlank=" + ctrl.isBlank() + " / trim().isEmpty=" + ctrl.trim().isEmpty());

        // NBSP を半角空白に置き換えてから判定する
        String replaced = nbsp.replace((char) 0x00A0, ' ');
        System.out.println("NBSP を置き換えた後の isBlank=" + replaced.isBlank());

        // 判定の基準になっているメソッド
        System.out.println("isWhitespace(全角空白)=" + Character.isWhitespace(' '));
        System.out.println("isWhitespace(NBSP)=" + Character.isWhitespace((char) 0x00A0));
    }
}

実行結果:

NBSP     isBlank=false / trim().isEmpty=false
ゼロ幅   isBlank=false / trim().isEmpty=false
制御文字 isBlank=false / trim().isEmpty=true
NBSP を置き換えた後の isBlank=true
isWhitespace(全角空白)=true
isWhitespace(NBSP)=false
文字 isBlank() trim().isEmpty() 入ってくる場面の例
ノーブレークスペース(U+00A0) false false Webページや表計算ソフトからのコピー
ゼロ幅スペース(U+200B) false false Webページからのコピー
制御文字(U+0001 など) false true 外部システムから届くデータ

ノーブレークスペースは「改行させない空白」で、Character.isWhitespace では空白に数えられません。 コピーして貼り付けた値で判定が合わないときは、上のコードのように半角空白へ置き換えてから isBlank() を呼ぶと対応できます。制御文字は trim() では取り除かれ、isBlank() では空白に数えられない、という逆の結果になる点も覚えておくと原因を探しやすくなります。

そのほかの書き方と比べる

空判定には、ほかにもいくつかの書き方があります。それぞれの動きを1つのコードで確認します。

import java.util.Objects;
import java.util.Optional;

public class Others {
    public static void main(String[] args) {
        String s = null;

        // "" を左に置くと、s が null でも例外にならない
        System.out.println("\"\".equals(s)                 = " + "".equals(s));
        System.out.println("\"\".equals(\"\")                = " + "".equals(""));

        // null を空文字に置き換えてから判定する
        System.out.println("Objects.toString(s, \"\")       = " + Objects.toString(s, "").isBlank());
        System.out.println("Objects.requireNonNullElse   = " + Objects.requireNonNullElse(s, "").isBlank());

        // Optional で書く
        boolean blank = Optional.ofNullable(s).map(String::isBlank).orElse(true);
        System.out.println("Optional                     = " + blank);

        // == で比べると、中身が同じ空文字でも false になることがある
        String empty = new String("");
        System.out.println("new String(\"\") == \"\"        = " + (empty == ""));
        System.out.println("new String(\"\").isEmpty()    = " + empty.isEmpty());
        System.out.println("new String(\"\").length()==0  = " + (empty.length() == 0));
    }
}

実行結果:

"".equals(s)                 = false
"".equals("")                = true
Objects.toString(s, "")       = true
Objects.requireNonNullElse   = true
Optional                     = true
new String("") == ""        = false
new String("").isEmpty()    = true
new String("").length()==0  = true
書き方 null のとき 特徴
"".equals(s) false(例外にならない) 空文字かどうかだけを調べる。null は空とみなさない
s.equals("") 例外 変数を左に置くと null で止まる
s.length() == 0 例外 isEmpty() と同じ判定
s == "" false 参照を比べるので、中身が空文字でも false になる場合がある
Objects.toString(s, "").isBlank() true null を空文字に置き換えてから判定する
Objects.requireNonNullElse(s, "").isBlank() true Java 9以降。null なら第2引数を使う
Optional.ofNullable(s).map(String::isBlank).orElse(true) true メソッドチェーンの途中で使いやすい

文字列を == で比べると、中身ではなく「同じオブジェクトかどうか」を比べます。 実行結果のとおり、new String("") と "" は中身が同じ空文字でも == では false になりました。空判定には isEmpty() か isBlank() を使うと、作り方に左右されません。

"".equals(s) は null で止まらない書き方ですが、null のときに false を返します。「null も空として扱いたい」場合は s == null || s.isEmpty() のほうが意図どおりになります。

文字列以外の空判定

isEmpty() は String 以外にも用意されています。文字列を組み立てる途中の StringBuilder や、コレクションの空判定も同じ名前で書けます。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class Builder {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        System.out.println("StringBuilder length()==0 : " + (sb.length() == 0));
        System.out.println("StringBuilder isEmpty()   : " + sb.isEmpty());   // Java 15 以降

        List<String> list = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        System.out.println("List isEmpty()            : " + list.isEmpty());
        System.out.println("Map isEmpty()             : " + map.isEmpty());
        System.out.println("配列 length == 0          : " + (new String[0].length == 0));
        System.out.println("Optional isEmpty()        : " + Optional.empty().isEmpty());  // Java 11 以降
    }
}

実行結果(OpenJDK 21.0.10):

StringBuilder length()==0 : true
StringBuilder isEmpty()   : true
List isEmpty()            : true
Map isEmpty()             : true
配列 length == 0          : true
Optional isEmpty()        : true
対象 空判定の書き方 補足
String s.isEmpty()、s.isBlank() isBlank() は Java 11以降
StringBuilder sb.length() == 0、sb.isEmpty() isEmpty() は Java 15以降。Java 8〜14 向けは length() == 0
List・Set・Map list.isEmpty() null のときは例外になるので、先に null を調べる
配列 arr.length == 0 配列に isEmpty() はない
Optional opt.isEmpty()、opt.isPresent() isEmpty() は Java 11以降

StringBuilder と Optional の isEmpty() が使えるバージョンは一般に知られた仕様として書いており、今回は Java 21 での動作だけを確認しています。

つまずきやすい点と直し方

空判定でよく出会う状況を、直す前と直した後で並べます。

状況 直す前 直した後
null で止まる if (s.isEmpty()) if (s == null || s.isEmpty())
空白だけの入力が通ってしまう if (s.isEmpty()) if (s == null || s.isBlank())
全角空白だけの入力が通ってしまう if (s.trim().isEmpty()) if (s.isBlank())
条件の順番が逆 if (s.isBlank() || s == null) if (s == null || s.isBlank())
空文字なのに一致しない if (s == "") if (s.isEmpty())
Java 8 でコンパイルできない s.isBlank() 自作の isBlank(s) か StringUtils.isBlank(s)
前後の全角空白が残る s.trim() s.strip()

直す前の書き方はどれも、特定の入力のときだけ結果が変わるものです。 6種類の入力(null・空文字・半角空白・全角空白・タブ・改行)をテストデータとして用意しておくと、書いた判定が意図どおりかをすぐ確かめられます。

確認用のチェックリスト

  • null が渡される可能性があるかを確認し、あるなら null を先に調べている
  • 空白だけの入力を空とみなすかどうかを決め、isEmpty() と isBlank() を選び分けている
  • 全角空白の入力をテストデータに入れている
  • 動かす Java のバージョンで isBlank() と strip() が使えることを確認している
  • 文字列の比較に == を使っていない
  • 空の値を null と空文字のどちらにそろえるかを決めている

よくある質問

Q. isEmptyとisBlankは、どちらを使えばよいですか? A. 人が入力した値を調べるなら isBlank() が合います。空白だけの入力や全角空白だけの入力も空として扱えるためです。空白も意味のある文字として数えたい場合は isEmpty() を選びます。どちらも null では例外になるので、s == null || を先に付けてください。

Q. StringUtilsは使ったほうがよいですか? A. すでに Apache Commons Lang を導入しているなら、StringUtils.isBlank(s) は null も含めて1回の呼び出しで判定できるので便利です。この記事の実行結果のとおり、s == null || s.isBlank() でも同じ判定になるので、ライブラリを追加しない場合はこちらで十分です。

Q. trim().isEmpty()をisBlank()に置き換えても結果は同じですか? A. 半角空白・タブ・改行では同じ結果です。全角空白だけの文字列では、trim().isEmpty() が false、isBlank() が true になります。また、U+0001 のような制御文字だけの文字列では逆に trim().isEmpty() が true、isBlank() が false でした。置き換えるときは、この2つの入力で結果が変わることを確認しておくと安心です。

Q. nullと空文字は、どちらにそろえるのがよいですか? A. どちらにも利点があります。空文字にそろえるとメソッドを呼んでも例外にならず、null にそろえると「値がない」ことをはっきり表せます。大切なのは、受け取った入口で1つの形にそろえ、チームで同じ方針を使うことです。

まとめ

  • isEmpty() は長さが0のときだけ true、isBlank() は空白だけの文字列も true(isBlank() は Java 11以降)
  • String のメソッドは null で NullPointerException になるので、s == null || を左側に書く
  • 全角空白を空と判定しないのは trim().isEmpty() だけ。日本語の入力には isBlank() と strip() が合う
  • Java 11以降の定型は s == null || s.isBlank()、Java 8 は Character.isWhitespace で1文字ずつ調べる
  • StringUtils.isBlank(s) は null も含めて1回で判定でき、定型コードと同じ結果になる
  • ノーブレークスペースとゼロ幅スペースは isBlank() でも空にならないので、必要なら置き換えてから判定する
  • 文字列の比較に == は使わず、isEmpty()・isBlank()・equals() を使う

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Java文字列の空判定|isEmptyとisBlankの違い早見表」

株式会社RJCでは、Javaの文字列の空判定のような基礎を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?