Apache Commons Lang(commons-lang3)のStringUtils.equalsは、2025年7月リリースの3.18.0から非推奨(@Deprecated)です。2026年9月25日公開の最新3.21.0でも非推奨のままですが、削除はされておらず呼び出せば従来どおり動きます。移行先はStrings.CS.equals(大文字小文字を区別)、equalsIgnoreCaseはStrings.CI.equalsです。この記事では、非推奨になった理由と対応表、Objects.equalsとの差、Spring Bootで警告が出ない理由を、JDK 25と3.21.0で実行した結果つきで説明します。
まとめ:StringUtils.equalsの非推奨と移行の要点
- 3.18.0で
equals/equalsIgnoreCase/contains/replace/indexOf/startsWithなど40個(オーバーロードを含む)のメソッドが非推奨になった。最新3.21.0でも同じで、削除はされていない。 - 移行先は
Strings.CS(大小を区別)とStrings.CI(大小を無視)。equalsはStrings.CS.equals、equalsIgnoreCaseはStrings.CI.equalsへ置き換える。 Objects.equalsで置き換えられるのは、比べる値がStringかnullの箇所。StringBuilderと比べると中身が同じでもfalseを返す。isEmpty/isBlank/substring/split/strip/right/abbreviateなどは非推奨ではない。- Spring Boot 3.5系はcommons-lang3を3.17.0に固定しているため、非推奨の警告が出ず、
Stringsクラスも存在しない。 - javacの既定では「Note」が2行出るだけでコンパイルは成功する。失敗するのは
-Xlint:deprecationで警告を有効にし、-Werrorも指定した構成だけ(-Werror単独では成功した)。
StringUtils.equalsが非推奨になった理由(3.18.0の設計変更)
3.18.0で新設されたStringsクラスは、大小を区別するStrings.CS(Case-Sensitive)と大小を無視するStrings.CI(Case-Insensitive)の2つのインスタンスを持ちます。equalsとequalsIgnoreCase、containsとcontainsIgnoreCaseのように、大小の扱いだけが違うメソッドがStringUtilsに2本ずつ並んでいた状態を、インスタンスの選択(CSかCIか)で表す形に改めたのが理由です。
非推奨の数はソースで確かめられます。3.17.0のStringUtils.javaで@Deprecatedが付いたpublic staticメソッドは13個でしたが、3.18.0では53個に増え、3.21.0も53個のままでした。増えた40個(オーバーロードを含む)が今回の移行対象で、移行先はほぼすべてStrings.CSかStrings.CIです。StringUtilsのJavadocではequalsに「Use Strings.CS.equals(CharSequence, CharSequence).」と書かれており、実装もStrings.CS.equalsを呼ぶだけです。
削除ではなく動作は継続(LANG-1777と3.21.0の状況)
非推奨の付いたメソッドは削除予定が告知されておらず、バイナリ互換も保たれています。一括の非推奨化には利用者側の反発があり、取り消しを求めるLANG-1777「Revert deprecations of 3.18.0」が起票されました。2026年10月15日時点でこのチケットはReopened(未解決)で、修正バージョンも空のままです。3.21.0のリリースノートにも非推奨を取り消す変更はありません。取り消しを待つより、新しく書くコードからStringsに寄せる方が無駄がありません。
javacの警告の出方(既定・-Xlint:deprecation・-Werror)
JDK 25.0.4でcommons-lang3 3.21.0を相手にStringUtils.equalsを1回呼ぶクラスをコンパイルすると、オプションごとに次の出力になりました。
$ javac -cp commons-lang3-3.21.0.jar Demo.java
Note: Demo.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
$ javac -Xlint:deprecation -cp commons-lang3-3.21.0.jar Demo.java
Demo.java:8: warning: [deprecation] equals(CharSequence,CharSequence) in StringUtils has been deprecated
1 warning
$ javac -Xlint:deprecation -Werror -cp commons-lang3-3.21.0.jar Demo.java
error: warnings found and -Werror specified
1 error
既定のままなら「Note」が出るだけで、classファイルは生成されます。-Werrorだけを付けた場合も、非推奨は「Note」の扱いのままなので成功しました。ビルドが止まるのは、-Xlint:deprecationで警告を有効にしたうえで、-Werror(MavenならfailOnWarning、Gradleならoptions.compilerArgsへの指定)を有効にしている構成です。
非推奨メソッドと移行先の対応表(Strings.CS / Strings.CI)
3.21.0で非推奨になっている主なメソッドと置き換え先です。使うにはimport org.apache.commons.lang3.Strings;を追加します。Stringsのメソッドはstaticではないので、Strings.CS.equals(...)のようにインスタンス経由で呼びます。
| 非推奨(StringUtils) | 移行先 |
|---|---|
| equals | Strings.CS.equals |
| equalsIgnoreCase | Strings.CI.equals |
| equalsAny / equalsAnyIgnoreCase | Strings.CS.equalsAny / Strings.CI.equalsAny |
| compare / compareIgnoreCase | Strings.CS.compare / Strings.CI.compare |
| contains(CharSequence検索) / containsIgnoreCase | Strings.CS.contains / Strings.CI.contains |
| containsAny(CharSequence…) | Strings.CS.containsAny |
| indexOf / lastIndexOf(CharSequence検索) | Strings.CS.indexOf / Strings.CS.lastIndexOf |
| startsWith / endsWith | Strings.CS.startsWith / Strings.CS.endsWith |
| replace / replaceOnce | Strings.CS.replace / Strings.CS.replaceOnce |
| removeStart / removeEnd | Strings.CS.removeStart / Strings.CS.removeEnd |
| appendIfMissing / prependIfMissing | Strings.CS.appendIfMissing / Strings.CS.prependIfMissing |
表のIgnoreCase版(startsWithIgnoreCase、removeEndIgnoreCaseなど)は、すべてStrings.CIの同名メソッドに対応します。
equalsの書き換えとObjects.equalsとの違い(実行結果)
3.21.0とJDK 25で、移行先と標準ライブラリの比較メソッドを並べて実行しました。以下はメソッド内に置く抜粋で、コメントは戻り値です。実行にはStringUtils、Strings、java.util.Objectsのimportが必要です。
StringBuilder sb = new StringBuilder("abc");
StringUtils.equals("abc", sb); // true(非推奨)
Strings.CS.equals("abc", sb); // true
Objects.equals("abc", sb); // false
"abc".contentEquals(sb); // true
Strings.CS.equals(null, null); // true
Objects.equals(null, null); // true
Objects.equals(a, b)は内部でa.equals(b)を呼ぶため、StringとStringBuilderのように型が違うと中身が同じでもfalseになります。StringUtils.equalsとStrings.CS.equalsは文字の並びで比べるのでtrueです。比べる両方がStringだと確定している箇所はObjects.equalsで標準ライブラリに寄せてよく、CharSequence型の引数やStringBuilderが混ざる箇所はStrings.CS.equalsに置き換えるのが安全です。
equalsIgnoreCase・contains・replaceの移行例
Strings.CI.equals("abc", "ABC"); // true(旧 equalsIgnoreCase)
Strings.CS.equalsAny("b", "a", "b"); // true(旧 equalsAny)
Strings.CI.containsAny("Hello", "xx", "LL"); // true(旧 containsAnyIgnoreCase)
Strings.CS.replace("aXbX", "X", "-"); // "a-b-"(旧 replace)
Strings.CI.removeEnd("report.CSV", ".csv"); // "report"(旧 removeEndIgnoreCase)
IDEの一括置換で移すときに間違えやすいのは、IgnoreCase付きのメソッドをStrings.CSに寄せてしまうことです。メソッド名からIgnoreCaseが消えるため、置換後のコードだけを見てもCSとCIの取り違えに気づけません。置換前に非推奨のシグネチャを確認し、対象の呼び出しだけを「IgnoreCase付き→CI」「それ以外→CS」に分けて移行します。置換後は大文字小文字を含む入力で結果を確認してください。
compareでnullを後ろに並べる指定(Strings.builder)
Strings.CSとStrings.CIは、compareでnullを小さい値として扱います。旧StringUtils.compare(str1, str2, false)のようにnullを大きい値として扱いたいときは、Strings.builder()で専用のインスタンスを作ります。
Strings.CS.compare(null, "a"); // -1(nullが先)
Strings nullLast = Strings.builder()
.setIgnoreCase(false)
.setNullIsLess(false)
.get();
nullLast.compare(null, "a"); // 1(nullが後)
3つ引数を取るStringUtils.compare(String, String, boolean)は3.21.0でも非推奨ではありません。非推奨なのは2引数のcompareだけです。
StringUtilsの打ち消し線とimport先の違い
StringUtilsという名前のクラスは複数のライブラリにあり、IDEの補完で別物をimportしていることがあります。打ち消し線や挙動の違いに気づいたら、まずimport文のパッケージを確かめてください。
| パッケージ | 非推奨の状況 | equals(null, null) |
|---|---|---|
| org.apache.commons.lang3 | equals等は3.18.0から非推奨 | true |
| org.apache.commons.lang(2.x) | ライブラリごと旧版 | true |
| org.springframework.util | isEmptyが5.3から非推奨 | equalsなし |
| software.amazon.awssdk.utils | 非推奨なし | false |
| org.apache.commons.codec.binary | 非推奨なし | true |
旧commons-lang(2.x)の識別と移行
import文がorg.apache.commons.lang.StringUtils(末尾がlang)なら、lang3とは別のレガシーライブラリです。2.xは2011年の2.6が最後の版で、CVE-2025-48924の影響範囲にも「commons-lang 2.0から2.6」が含まれています。CVEの公表文では、修正を含むlang3の3.18.0への更新が推奨されています。
SpringのStringUtils.isEmptyの非推奨化と代替API
「StringUtils.isEmpty 非推奨」で調べている場合、多くはSpring Frameworkのorg.springframework.util.StringUtilsです。SpringのisEmpty(Object)は5.3で@Deprecated(since = "5.3")になり、hasLengthやhasTextなどが代替として案内されています。String型の値で従来の空判定を保つには!StringUtils.hasLength(value)を使います。!StringUtils.hasText(value)は空白だけの文字列も空と判定するため、意味が変わります。commons-lang3のisEmptyは非推奨ではないので、移行先も別物です。
AWS SDKとcommons-codecのStringUtils.equalsにおけるnull比較
AWS SDK for Java v2のsoftware.amazon.awssdk.utils.StringUtils.equalsは、引数の片方でもnullならfalseを返し、両方nullでもfalseです。この挙動はJavadocと食い違っているとissue #6603で報告され、メンテナーは2026年1月5日のコメントで、戻り値を変えると破壊的変更になるとしてJavadoc側を実装に合わせたと説明しています。utils 2.56.0のソースでも、Javadocの例はStringUtils.equals(null, null) = falseで、実装も同じです。commons-codecのorg.apache.commons.codec.binary.StringUtils.equalsは1.23.0でも非推奨ではなく、両方nullでtrueを返します。lang3から移るつもりでこの2つに置き換えると、nullの扱いが変わる場合があります。
Spring Bootで警告が出ない・Stringsが見つからない原因(BOMが固定する版)
Spring Bootの依存管理(BOM)はcommons-lang3の版を決めています。各系列の最新版のspring-boot-dependenciesのpomを読むと、次の値でした。
| Spring Boot | commons-lang3 | Strings | equalsの非推奨 |
|---|---|---|---|
| 3.5.16 | 3.17.0 | なし | 出ない |
| 4.0.8 | 3.19.0 | あり | 出る |
| 4.1.1 | 3.20.0 | あり | 出る |
Spring Boot 3.5.16のpomはcommons-lang3.versionを3.17.0にしています。Maven 3.9.11でspring-boot-starter-parent 3.5.16を親にし、版を書かずにcommons-lang3を追加すると、解決される版は3.17.0でした。この構成ではStringUtils.equalsに打ち消し線は出ず、記事やAIの回答どおりStrings.CS.equalsに書き換えると、コンパイルでerror: cannot find symbol(import org.apache.commons.lang3.Strings;の行)になります。Spring Bootの各系列のサポート期限はSpring Bootバージョン一覧とサポート期限(EOL)【2026年10月】最新版は4.1、4.0の無償サポートは12月末終了にまとめています。
実行時のNoClassDefFoundError
3.21.0でコンパイルしたクラスを3.17.0のjarで実行すると、非推奨のStringUtils.equalsまでは動き、次のStrings.CS.equalsの行で止まりました。
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/Strings
at Demo.main(Demo.java:9)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.Strings
ライブラリを作っていて利用側のアプリケーションが版を決める場合や、アプリケーションサーバーが共通ライブラリとして古いlang3を持っている場合に起きます。mvn dependency:tree -Dincludes=org.apache.commons:commons-lang3で、実際に解決される版を確認してから移行してください。
Spring Bootで管理版を上書きする方法
spring-boot-starter-parentを使うMavenプロジェクトでは、propertiesで版を上書きできます。Maven 3.9.11とSpring Boot 3.5.16で、この指定により解決される版が3.17.0から3.21.0に変わることを確認しました。
<properties>
<commons-lang3.version>3.21.0</commons-lang3.version>
</properties>
Gradleでio.spring.dependency-managementプラグインを使っている場合は、build.gradleにext['commons-lang3.version'] = '3.21.0'を書きます。
非推奨ではない主要メソッドの実行結果
大小の2系統を持たないメソッドは非推奨の対象外です。3.21.0で実行した結果を示します。
StringUtils.isEmpty(" "); // false(空白1文字は空ではない)
StringUtils.isBlank(" "); // true
StringUtils.substring("abc", 5); // ""(範囲外でも例外なし)
StringUtils.split("a,,b", ","); // [a, b](空要素を除く)
StringUtils.splitPreserveAllTokens("a,,b", ","); // [a, , b]
StringUtils.right("2026-10-15", 5); // "10-15"
StringUtils.right(null, 5); // null
StringUtils.abbreviate("commons-lang3", 8); // "commo..."
StringUtils.isNumeric("123"); // true(全角数字も数字扱い)
StringUtils.isNumeric("-1"); // false(符号は不可)
StringUtils.defaultIfBlank(" ", "N/A"); // "N/A"
見落としやすいのはsplitとisNumericです。splitは連続した区切り文字の間の空要素を捨てるので、空欄に意味がある単純な区切り文字列ではsplitPreserveAllTokensを使います。引用符内のカンマや改行を含むCSVには、Apache Commons CSVなどのCSVパーサーを使ってください。isNumericは全角の「123」をtrueと判定するため、Integer.parseIntの前のチェックに使うと、全角数字がそのまま渡ります。
stripとtrimの違い(全角スペース)
StringUtils.strip(" 全角 "); // "全角"
StringUtils.trim(" 全角 "); // " 全角 "(全角スペースが残る)
stripはCharacter.isWhitespaceで判定するため全角スペース(U+3000)も取り除きます。trimはString.trimと同じく文字コード32以下だけを取り除くので、全角スペースは残ります。日本語のフォーム入力を正規化するならstripを使います。
移行するかの判断基準(急ぐ場面と急がない場面)
動いている既存コードを、警告を消すためだけに一斉に書き換える必要はありません。対応は、警告によるビルド失敗、脆弱性対策のための更新、利用側との互換性維持に分けて判断します。
-Xlint:deprecationと-Werror(またはfailOnWarning)で警告をエラー扱いにしていて、lang3を3.18.0以上に上げる予定がある。- lang3が3.18.0未満のまま残っている。CVE-2025-48924(
ClassUtils.getClassに非常に長い文字列を渡すとStackOverflowError)は3.0以上3.18.0未満が対象です。非推奨の警告を避けるために3.17.0に留めると、この修正も受けられません。 - ライブラリとして配布していて、利用側のlang3の版を選べない。この場合は逆に
Stringsを使わず、StringUtilsのまま書く方がNoClassDefFoundErrorを避けられます。
それ以外の場面では、新しく書くコードをStrings.CS/Strings.CIで書き、既存コードは触ったファイルから順に置き換えれば足ります。複数のモジュールで共通部品の版がそろっていない業務システムでは、まず依存の版を一本にそろえる方が先です。Javaの業務システムの改修や新規構築を外部に相談したい場合は、フルスクラッチ開発の支援内容も参考にしてください。
Apache Commons Lang3の導入(Maven / Gradle)
2026年10月15日時点の最新版は3.21.0です(Maven Central)。Stringsクラスは3.18.0以上にしか無く、jarのクラスファイルはJava 8(major version 52)向けにコンパイルされているので、Java 8の環境でも使えます。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.21.0</version>
</dependency>
implementation("org.apache.commons:commons-lang3:3.21.0")
Mavenでの依存追加の流れはJacksonをMavenで導入する手順|2.22と3.2の依存の違いとObjectMapper・JsonNodeの使い方と同じ要領です。Gradleでコンパイルに使うJDKの版をそろえる方法はツールチェーン(toolchain)とは?構成要素と言語別の実例・GradleのJava Toolchain設定で扱っています。
よくある質問
StringUtils.equalsは将来削除されますか?
2026年10月15日時点で削除の予定は告知されていません。最新の3.21.0でも@Deprecatedが付いているだけで動作します。非推奨の取り消しを求めるLANG-1777は未解決のままです。
StringUtils.equalsの代わりにObjects.equalsを使っても大丈夫ですか?
比べる両方がStringなら同じ結果です。文字の並びが同じStringとStringBuilderを比べるとObjects.equalsはfalse、Strings.CS.equalsはtrueを返すため、CharSequenceが混ざる箇所はStrings.CS.equalsに置き換えてください。
StringUtils.isEmptyやisBlankも非推奨ですか?
commons-lang3のisEmpty/isBlank/isNotBlankは非推奨ではありません。非推奨なのはSpring Frameworkのorg.springframework.util.StringUtils.isEmptyで、5.3からhasLength/hasTextへの移行が案内されています。真偽が逆になるので!StringUtils.hasLength(value)と否定して置き換えます。
equalsIgnoreCaseの移行先は何ですか?
Strings.CI.equals(s1, s2)です。CIはCase-Insensitive(大文字小文字を無視)の略で、旧equalsIgnoreCaseと同じ結果になります。
Strings.CS.equalsが見つからないと言われるのはなぜですか?
使っているcommons-lang3が3.18.0未満です。Spring Boot 3.5系は既定で3.17.0を使うため、commons-lang3.versionプロパティで3.18.0以上に上書きしてください。