Java中級:文字列・日付・標準ライブラリのよくある間違い

レッスンの本文で注意している点を、つまずきの側から27件ぶん並べ直しました。書いた覚えのある形が見つかったら、 そのままレッスンに戻って前後を読めます。

String.format で書式化

レッスンを読む

%dString を渡してしまう

String.format("%d", "100") のように、文字列を %d の位置に入れると、IllegalFormatConversionException という実行時例外が飛びます。整数なら %d、文字列なら %s、と型を必ず合わせましょう。逆に %s には int でも double でも何でも入れられる (自動で toString() される) ので、迷ったときの保険として %s は便利です

String.format で書式化で詳しく読む

\n%n を取り違える

改行を入れたいとき、\n は環境にかかわらず常に LF (0x0A) になりますが、%n は OS ごとの改行 (Windows なら CRLF、Linux/macOS なら LF) に展開されます。ログや帳票を Windows でも Linux でも揃えたいときは %n を、HTML などプラットフォーム非依存で必ず LF にしたいときは \n を、というふうに使い分けます

String.format で書式化で詳しく読む

桁あふれと意図しない丸め

%.2f の丸めは HALF_UP(いわゆる四捨五入)です。ただし double/float0.10.2 などを二進浮動小数点で正確に表現できないため、表示する前の値そのものに微小な誤差が乗ります。お金の計算など厳密な精度が必要なときは BigDecimalsetScale(2, RoundingMode.HALF_UP) を使うのが安全です。String.format%.2f はあくまで「画面表示用の見た目を整える」ためのもの、と割り切りましょう

String.format で書式化で詳しく読む

StringBuilder で連結

レッスンを読む

toString() の呼び忘れ

String result = sb; と書くとコンパイルエラーです。String result = sb.toString(); のように明示的に呼び出してください。println のように Object#toString を内部で使ってくれるメソッドなら不要ですが、String 型の変数に入れるときや、API の引数として渡すときは必ず変換が必要です

StringBuilder で連結で詳しく読む

ループ外で + 連結を 1 回だけする場合に StringBuilder を持ち出す

String full = first + " " + last; のように、定数回 (2〜3 回) の連結なら、コンパイラが自動で StringBuilder 相当のコードに変換してくれます。乱用するとかえって読みにくくなるので、for while などのループ内で繰り返し連結するときに使うのが本来の使いどころです

StringBuilder で連結で詳しく読む

初期容量を指定せず巨大な文字列を組み立てる

new StringBuilder() のデフォルト容量は 16 文字です。1 万文字以上を作ると分かっているなら、new StringBuilder(10_000) のように指定しておくと内部配列の再確保が発生せず高速です。性能を気にする場面では覚えておきましょう

StringBuilder で連結で詳しく読む

正規表現の基本

レッスンを読む

\\ のエスケープ忘れ

Java の文字列で \d \w \s を書きたいときは必ず \\d \\w \\s のようにバックスラッシュ 2 つです。1 つしか書かないとコンパイルエラー (illegal escape character) になります

正規表現の基本で詳しく読む

matches を部分一致だと思い込む

String.matches は 完全一致 です。"foo bar".matches("foo")false を返します。部分的に含まれているかを調べたいなら s.contains("foo") を使うのが手軽です

正規表現の基本で詳しく読む

greedylazy の混同

* + ? はデフォルトで greedy (できるだけ長くマッチ) です。最小マッチにしたいときは *? +? のように ? を後ろに付けます。今回の課題のような単純な完全一致では気にしなくて構いません

正規表現の基本で詳しく読む

split と join

レッスンを読む

split の引数に正規表現特殊文字をそのまま渡す

"." "|" "?" などはエスケープしないと意図どおりに動きません。split("\\.") split("\\|") のようにバックスラッシュ 2 つでエスケープするか、Pattern.quote を使いましょう

split と joinで詳しく読む

空文字列を split した結果を空配列だと思い込む

"".split(",") は要素 1 個の配列 [""] を返します。空入力に対して空文字列を返したいときは、csv.isEmpty() で先に判定するのが安全です

split と joinで詳しく読む

末尾の空要素が消える仕様を知らない

"a,b,,".split(",") は 2 要素しか返しません。CSV の列数を厳密に揃えたいときは split(",", -1) を使って末尾の空要素を保持してください

split と joinで詳しく読む

LocalDate で日付を扱う

レッスンを読む

java.util.Date を使ってしまう

IDE の自動 importDate を選ぶと、java.util.Date が候補に出ます。今からの新規コードでは必ず java.time.LocalDate の方を選びましょう。import 文を確認する癖をつけると安全です

LocalDate で日付を扱うで詳しく読む

月を 0 始まりだと思い込む

Calendar 時代の名残で「5 月4」と書いてしまう人がいます。LocalDate.of(2026, 5, 19)5 はそのまま 5 月 です。0 を渡すと DateTimeException が出ます

LocalDate で日付を扱うで詳しく読む

戻り値を捨てる

date.plusDays(1); と書いても、戻り値を受け取らないと意味がありません。LocalDate は不変なので、必ず date = date.plusDays(1); のように再代入するか、別の変数に受けてください

LocalDate で日付を扱うで詳しく読む

LocalDateTime で時刻も扱う

レッスンを読む

yyyyYYYY を取り違える

小文字 yyyy が普通の暦年 (2026)、大文字 YYYYweek-based-year という年またぎ週の特殊な年を表します。たとえば 2025-12-29 (月) のように年末が月曜から始まる週だと、YYYY2026 を返すことがあります。請求書や領収書を作るときに混入すると、「なぜか 1 件だけ翌年扱い」というバグになるので、 を出したいときは必ず小文字 yyyy を使います

LocalDateTime で時刻も扱うで詳しく読む

MM (月) と mm (分) を取り違える

yyyy-mm-dd hh:MM のように書いてしまうと、月のはずの位置に分が、分のはずの位置に月が入り、2026-30-19 02:05 のような壊れた文字列ができあがります。日本語で書くと「月は大文字 MM、分は小文字 mm」、と語呂で覚えるのが安全です

LocalDateTime で時刻も扱うで詳しく読む

SimpleDateFormat を使ってしまう

旧 API の java.text.SimpleDateFormat は今でも import できますが、スレッドセーフでないため、ServletSpring のように複数リクエストが同時に走る環境で共有変数として持つと、たまに壊れた文字列を返すという最悪のバグになります。新規コードでは必ず DateTimeFormatter を使い、SimpleDateFormat は触らないのが鉄則です

LocalDateTime で時刻も扱うで詳しく読む

Duration で時間差を計算

レッスンを読む

Duration に年や月の長さを聞かない

Duration は最大単位が「日」ですが、toDays() の戻り値も「秒数を 86400 で割った値」にすぎず、Duration 自体は「年 / 月」の概念を持っていません。Duration.ofDays(60).toMonths() のようなメソッドはなく、書こうとしてもコンパイルエラーになります。年・月単位の差を取りたいときは Period または ChronoUnit.MONTHS.between を使いましょう

Duration で時間差を計算で詳しく読む

Period で秒や時間を扱おうとする

逆に、Period.between(localTime1, localTime2) は 型エラー になります。PeriodLocalDate 専用で、LocalTimeLocalDateTime を渡せません。「ストップウォッチ的な短い時間」を測りたいときは必ず Duration を使います

Duration で時間差を計算で詳しく読む

between の引数順を逆にして符号がおかしくなる

ChronoUnit.DAYS.between(start, end)end - start を返します。start のほうが未来だと 負の値 になります。「絶対値が欲しい」のか「向きを保ちたいのか」を意識して書きましょう。Math.abs(...) で絶対値を取るのは簡単ですが、「過去か未来か」の情報を捨てる前に、本当にそれでいいかを一度立ち止まって考えるのが大事です

Duration で時間差を計算で詳しく読む

日付の書式化とパース

レッスンを読む

yyyyYYYY を混同する

小文字の yyyy は普通の暦年ですが、大文字の YYYY週ベースの年 を意味します。年末年始をまたぐ ISO 週で結果がズレるため、Windows のメモ帳で書いた仕様書をコピペしたら 1 月 1 日が 2027 年扱いになる、というバグが起きやすいです。日付 を出すときはほぼ常に小文字の yyyy が正解です

日付の書式化とパースで詳しく読む

MMmm の取り違え

大文字の MM は月、小文字の mm は分。これを逆に書くと、yyyy/mm/dd というパターンが「年/分/日」と解釈されます。LocalDate には時刻情報がないため分は常に 0 となり、2026/00/19 のような意図しない出力になります。コンパイルエラーにならない分、見つけにくい不具合です

日付の書式化とパースで詳しく読む

HHhh の取り違え

HH/hhLocalDateTimeLocalTime など時刻を持つ型で使うパターンです。LocalDate には時刻フィールドがないため、このミスが実害として現れるのは時刻を扱う型が対象のときです。24 時間制で表示したいのに hh と書くと 12 時間制 (112) になります。午後 3 時が 03 と表示されてしまい、AM/PM の区別 (a パターン) を入れ忘れると 03:00 が午前か午後か分からなくなります。業務アプリでは原則 HH を使うと覚えてください

日付の書式化とパースで詳しく読む

日付の加減算

レッスンを読む

戻り値を捨ててしまう

today.plusDays(10); と書いただけで、戻り値を変数に代入し忘れるのが一番多いミスです。LocalDate は不変なので、戻り値を捨てると計算結果はどこにも残りません。必ず LocalDate later = today.plusDays(10); のように受け取りましょう

日付の加減算で詳しく読む

月またぎを手で計算しようとする

5/305 日足したいから「日 = 30 + 5 = 355 月は 31 日までだから 4 を引いて 6/4」のような計算は不要です。plusDays(5) に任せれば一発です。月またぎ・年またぎ・うるう年は API がすべて面倒を見てくれます

日付の加減算で詳しく読む

不変オブジェクトを誤解する

Calendar 時代の感覚で today.plusDays(10) を呼んだら today 自身が変わると思い込むパターンです。Stringreplace と同じく、LocalDateplus* minus* with* はすべて新しいインスタンスを返します。元のオブジェクトは絶対に変わりません

日付の加減算で詳しく読む