Javaの文法は一通り覚えた。クラスも書ける。Streamも使える。

そこから先で待っているのが、「動くのに、なぜか変」という段階です。原因はたいてい、言語の仕様の中にある小さな約束ごと。今回は、書けるようになった人が次にぶつかる8つ——Java歴1〜3年の人にこそ効くものを集めました。1つでも知らなかったら儲けものです。

① Integerは、127までは == が使えて、128から使えません

いちばん有名で、いちばん踏まれる話から。

Integer a = 127, b = 127;
System.out.println(a == b);   // true

Integer c = 128, d = 128;
System.out.println(c == d);   // false !?

Javaは-128〜127のIntegerをあらかじめ作り置きして使い回す(IntegerCache)ので、127までは同じオブジェクト、128からは毎回別のオブジェクトになります。

== はオブジェクトの同一性、equalsは値の等しさ。参照型の比較は必ずequals——この事故は、テストデータが小さいときだけ通ってしまうのが怖いんです。

② equalsを書いたら、hashCodeも書かないと消えます

自作クラスをHashMapのキーやHashSetの要素にするとき、equalsだけ実装していませんか。

HashMapは、まずhashCodeで置き場所を決め、その場所の中でequalsで探します。hashCodeが違えば、equalsが真でも別の場所を探しに行く——つまり「入れたはずのものが見つからない」が起きます。

equalsとhashCodeは、必ずセットで実装する。現代なら、⑧のrecordを使えば両方自動生成されるので、こちらの方が安全なんです。

③ finallyの中でreturnすると、例外が消えます

知らないと、障害調査で地獄を見る仕様です。

try {
    throw new RuntimeException("大事なエラー");
} finally {
    return "OK";   // 例外が握りつぶされ、"OK"が返る
}

finallyでreturnすると、tryやcatchで発生した例外は破棄され、正常終了したように見えます。ログにも残りません。

finallyは後始末専用、returnは書かない。IDEが警告を出す理由が、これなんです。

④ List.of() には、nullを入れられません

Java 9以降の便利なファクトリ、実は性格がはっきりしています。

List.of() / Map.of()Arrays.asList()
要素の追加・削除できない(例外)できない(例外)
要素の上書き(set)できない(例外)できる
nullを入れるその時点でNullPointerException入れられる

List.of()は完全に不変、Arrays.asList()は「サイズ固定だがsetはできる」という中途半端な存在です。

「不変にしたいのか」「後で変えたいのか」を、作るときに選ぶ。この意識があるだけで、意図しない変更事故が減ります。

⑤ Streamは、終端操作を呼ぶまで1ミリも動きません

Streamの中間操作(filter、map…)は、予約を積んでいるだけです。

list.stream().map(x -> {
    System.out.println("処理中");  // 何も出ない
    return x * 2;
});
// collect や forEach を呼んで、初めて動く

これは遅延評価という設計で、無限ストリームやショートサーキットを可能にする良い性質です。

もう1つ大事なのが、Streamは一度使ったら再利用できないこと。同じStream変数を2回回すと IllegalStateException。使い捨ての川、と覚えると事故りません。

⑥ ラムダの中で、チェック例外は投げられません

Streamで処理を書いていて、IOExceptionを投げるメソッドを呼んだ瞬間にコンパイルエラー——通過儀礼です。

理由は、Streamに渡す関数型インターフェース(Function等)が、チェック例外を投げる宣言を持っていないから。ラムダの中身は、そのインターフェースの契約に縛られます。

対策は、ラムダ内でcatchして非チェック例外に包み直すか、そういう処理はStreamの外で普通のforに戻すか。

「全部Streamで書く」より「例外が絡むなら素直にfor」の方が、読みやすいことも多いんです。

⑦ switchは、式になりました

Java 14以降、switchは「文」だけでなく「値を返す式」として書けます。

String label = switch (day) {
    case SAT, SUN -> "休日";
    case MON, TUE, WED, THU, FRI -> "平日";
};

アロー(->)形式なら、break忘れによるフォールスルー事故が構造的に起きません。さらに、enumやsealedと組み合わせると「全ケースを網羅していないとコンパイルエラー」になります。

「switchにbreakを書き忘れる」という20年来のバグが、書き方ひとつで消えるんです。

⑧ recordは、「データを運ぶだけ」のクラスを1行にします

最後は、書く量が減る話です。

record Point(int x, int y) {}

これだけで、コンストラクタ・アクセサ・equals・hashCode・toStringが自動生成され、フィールドは不変になります。②のhashCode問題も、④で触れた不変性も、recordなら最初から正しい。

ただし不変なのは「フィールドの付け替え」まで。Listのような可変オブジェクトを持たせると、その中身は変更できてしまうので、List.copyOf()で包むのが定石です。

DTOやAPIのレスポンスクラスにgetterを何十行も書いていた時代は、終わっています。「このクラスの仕事はデータを運ぶだけか」——YESなら、record一択なんです。

番外編:知っておくと得する小ネタ

enum.values() は毎回コピーを作ります
呼ぶたびに新しい配列を生成するので、ループ内で何度も呼ぶと無駄が出ます。頻繁に使うなら、一度取って保持しておくんです。

Java 21は、堅い業界でも現役です
長期サポート版のJava 21は、record・switch式・仮想スレッドが全部使えます。最新の長期サポート版はJava 25で、2026年9月にはJava 27も登場しました。堅い業界のプロジェクトでも、21以降は現役の選択肢です。

varは「型を書かない」だけで「型がない」わけではない
var x = 1; のxは、あくまでint。コンパイル時に型は確定しています。動的型付けとは別物なんですね。

RJCでも、Javaと向き合っています

RJCの研修はJavaから始まり(Lv.01〜03で環境構築・Java・オブジェクト指向)、実際の案件でも金融業界向けのJava 21プロジェクトなどで開発しています。

社内のJava探求グループでは、まさに今日のような「仕様の細部」を持ち寄って掘り下げています。こういう話を、Techチームで共有しながら開発しています。

よくいただくご質問

Q. まずどれから押さえるべきですか?
A. ①と②です。比較とハッシュの約束は、コレクションを使う全コードに関わるので、今日のレビューから効くんですよね。

Q. 古いJavaのプロジェクトなので、⑦⑧が使えません…
A. その環境なら①〜⑥だけでも十分効きます。そして新しい構文を知っていること自体が、バージョンアップの提案材料になります。

Q. Streamとforは、どう使い分ければいいですか?
A. 変換・絞り込みが主ならStream、例外や複雑な分岐が絡むならfor(⑥)。「読んだ人が一番早く理解できる方」が正解なんですよね。

Q. 未経験からでも、ここまで分かるようになりますか?
A. なります。RJCの研修でも、Javaの基礎から4ヶ月でSpring Bootまで進みます。今日の8つは、その途中で必ず出会う話ばかりなんです。

「動く」と「正しい」の間に、仕様があります

今日の8つに共通していたのは、これでした。

Javaは動いてしまう言語です。==で比較しても、finallyでreturnしても、コンパイルは通る。違いが出るのは、境界値や例外時、つまり本番の一番嫌なタイミングです。

仕様を知っている人は、そこで慌てない。中級の壁は、文法ではなく約束ごとの理解なんですよね。

みなさんがJavaで踏んだ「仕様どおりだった事故」、よかったら教えてください。

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で一緒に開発しながら、 成長を楽しみませんか?