Javaを学びはじめた頃、私は IllegalArgumentException
に出会いました。
エラーを見た瞬間、思ったのは――「何これ?こわっっ!!」。
そもそも「引数ってなに?仲良くなれるやつ?」みたいな状態だった私は、エラーメッセージに対してただただ固まるばかり。
“Illegal” とか “Argument” とか、英語圏のケンカが起きてるみたいでさらにこわい。
でも、ちゃんと向き合ってみると、このエラーは「その引数、ちょっとマズいかもよ?」とやさしくプログラムを守ってくれていた存在だと気づきました。
今では、エラーが出ても「はいはい、また君か」くらいのノリで付き合えるようになり、Javaライフを楽しんでいます。
この記事では、そんな IllegalArgumentException
の 起こる仕組み 、よくあるミスパターン、対処法と予防策を、私の“やらかし経験”も交えながら、やさしく解説していきます。
「引数って、なんかむずそう」と思っている方にも、きっとヒントになるはずです。
それでは、一緒に見ていきましょう!
IllegalArgumentExceptionとは?
――「値として受け取れるけど、受け取れません!」
“Illegal”ってついてるけど、別に法的にアウトな話ではありません
IllegalArgumentException(読み:イリーガル・アーギュメント・エクセプション)は、Javaで実行時に発生する例外のひとつです。
名前のインパクトが強めなので、初めて見ると「うわっ、なんかやばそう…!」とビビりますが、実はとても理にかなった例外なのです。
この例外の意味をざっくり説明すると:
「その引数、型としては合ってるけど、“内容”が無効だから受け取れません」
たとえば、Thread.sleep(-1000) のように “負の数” を渡すと、 Javaは「いやいや、マイナスで寝る時間ってどういうこと?」と突っ込んで IllegalArgumentException を投げてきます。
どんなときに発生するの?
この例外は主に、メソッドの引数がロジック的に不正だった場合に、メソッド側から明示的にスローされることが多いです。
たとえばこんなコード
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年齢は0以上である必要があります");
}
this.age = age;
}
このように、メソッドの中で「受け取った値がおかしい」と判断した場合に、自らこの例外を投げるのが一般的です。
チェック例外との違い
IllegalArgumentException は「非チェック例外(RuntimeException)」に分類されるため、呼び出し側で throws を書かなくてもよい代わりに、 「この引数が無効だったら落ちますよ」という約束を文書やドキュメントでしっかり伝える必要がある例外でもあります。
その点で、IOException や SQLException のようなチェック例外とは性質が異なります。
他にもよくある例
発生場所 | 不正な引数 |
---|---|
ArrayList.subList(-1, 2) | 範囲外のインデックス |
Thread.sleep(-100) | 時間に負の数を指定 |
Integer.valueOf(null) | null(NullPointerException の可能性も) |
自作メソッドで明示的に投げる | 「0以下は受け付けません」などバリデーションで |
この章のまとめ
- IllegalArgumentException は 「引数は型的にはOKだけど、意味的にNGなとき」に発生する例外
- 多くはメソッド内で明示的に throw される
- 引数にどんな値を渡せるか(=契約)を意識することが、設計の質に直結する
- 名前は物騒だけど、「お願い、それだけはやめて…!」という コードからのやさしい悲鳴
よくある発生例
――「受け取ったけど、それじゃ無理」なパターン集
見た目はOK。でも中身がダメなんです
IllegalArgumentException は、型としては合っているけれど、値の内容が想定外だったときに発生します。
ここでは、「それっぽく見える引数」がなぜ怒られるのか、実際のコードとともに見てみましょう。
ケース①:マイナスの値を渡してしまった
Thread.sleep(-1000); // ❌ エラー発生
理由:
- sleep() メソッドは「何ミリ秒スリープするか」を指定します。 マイナスの時間って何…?と、Javaは当然拒絶。
実行時エラー:
java.lang.IllegalArgumentException: timeout value is negative
ケース②:配列やリストのインデックス範囲がおかしい
List<String> list = Arrays.asList("A", "B", "C");
List<String> sub = list.subList(-1, 2); // ❌
理由:
- -1 はリストの範囲外。IndexOutOfBoundsException っぽく見えて、 実は「その値、論理的に無効だよ」と IllegalArgumentException を投げるメソッドもあります。
ケース③:自作メソッドで明示的に弾いている
public void setPrice(int price) {
if (price < 0) {
throw new IllegalArgumentException("価格は0以上にしてください");
}
this.price = price;
}
理由:
- 呼び出し側が setPrice(-300) としても、メソッド側で「ダメです」と弾く仕様になっているから。
このように、開発者が設計上“受け取りたくない値”を明示的に拒否するケースがとても多いです。
ケース④:Enumや限定値でチェック漏れ
public void setColor(String color) {
if (!List.of("RED", "GREEN", "BLUE").contains(color)) {
throw new IllegalArgumentException("指定できる色は RED, GREEN, BLUE のみです");
}
}
理由:
- 仕様上、受け入れたい値のリストがあらかじめ決まっている場合。 それ以外を渡されたときは、明示的に拒否することでバグを未然に防げます。
この章のまとめ
- IllegalArgumentException は「値の中身が理論的にNGなとき」に発生する
- よくある例:
負の数
範囲外のインデックス
許可されていない選択肢 - 多くのケースでメソッド内に明示的なチェック(if文+throw)が含まれている
エラーメッセージの読み方とデバッグのコツ
――Javaの「その値は無理!」を正しく受け取ろう
エラーメッセージ、実はかなり親切です
Javaの例外メッセージ、最初はちょっと intimidating(こわい)かもしれませんが、 実は非常に具体的で、まっすぐな“ヒント”をくれる存在です。
たとえばこんなメッセージ
Exception in thread "main" java.lang.IllegalArgumentException: timeout value is negative
at java.base/java.lang.Thread.sleep(Native Method)
at Sample.main(Sample.java:5)
このメッセージからわかることはたくさんあります。
分解してみよう
部分 | 説明 |
---|---|
IllegalArgumentException | 発生した例外の種類(引数の内容が不正) |
timeout value is negative | 原因の説明。何がどう悪いか明記されている |
at Sample.main(Sample.java:5) | どのクラスの何行目で発生したか |
つまり:
「5行目の Thread.sleep() にマイナス値を渡したけど、それじゃ無理だよ」
というJavaからのやさしい報告
スタックトレースの見方のコツ
- 一番上の例外タイプを見る → IllegalArgumentException(←何が原因かの入り口)
- メッセージを読む → “bound must be positive” や “index out of range” など、かなり具体的に書いてある
- どこで発生したか確認 → at クラス名.メソッド名(ファイル名:行番号) の形で表示される → 自作メソッドならその中の引数チェックを見に行こう!
自分で投げた場合もメッセージが超大事
if (age < 0) {
throw new IllegalArgumentException("年齢には0以上の値を指定してください");
}
こう書いておくと、エラー時に:
IllegalArgumentException: 年齢には0以上の値を指定してください
と表示され、呼び出し元の開発者にも親切な例外メッセージになります。
ログに出すときも getMessage() を活用しよう
try {
doSomethingDangerous(arg);
} catch (IllegalArgumentException e) {
System.err.println("入力値エラー:" + e.getMessage());
}
これならユーザーへの通知やログ出力にも適した形で情報を伝えられます。
この章のまとめ
- IllegalArgumentException は原因が明記されていることが多く、メッセージに必ずヒントがある
- スタックトレースは“どこで、なにが、なぜ怒られたか”を教えてくれる地図
- 例外メッセージを丁寧に書く習慣は、未来の自分や他人への優しさになる
事前に防ぐには?
――バリデーションと責任の切り分け
“悪い値が来る前提”でコードを書いてみる
IllegalArgumentException の多くは、「型は合ってるけど、中身がヘンな値」を渡されたときに発生します。
そこで大切なのが、「そもそも変な値が来る可能性を想定しておくこと」です。
Javaが怒るより先に、こちらから「その値、大丈夫?」と確認できるようにしておくことが、事故を防ぐ一番の近道です。
呼び出し側でチェックすべきか?中でチェックすべきか?
バリデーションは、いつ・どこでするのか? 実は奥が深いテーマです。
① 呼び出し側で行う例(外部入力を信頼しない)
if (inputAge >= 0) {
user.setAge(inputAge);
} else {
System.out.println("年齢は0以上を指定してください");
}
メリット: 呼び出し前に無効な値をブロックでき、例外が起きにくくなる。
デメリット: 呼び出し漏れがあると事故る(=再利用性が下がる)。
② メソッド内で防御する例(中で守る=防御的プログラミング)
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年齢は0以上である必要があります");
}
this.age = age;
}
メリット: メソッドが 「勝手に守ってくれる存在」 になる。
デメリット: 例外をスローするので、呼び出し側にも try-catch の考慮が必要になる。
ユースケースで使い分けよう
シーン | バリデーションの場所 |
---|---|
ユーザー入力やフォーム値 | 呼び出し側で早めに弾く |
ライブラリ・ユーティリティメソッド | 内部でしっかり守る |
業務ロジックの集約処理 | 両側での二重ガードも検討可 |
Java標準&便利ライブラリを活用しよう
Objects.requireNonNull()(標準API)
this.name = Objects.requireNonNull(name, "nameはnullにできません");
Guavaの Preconditions.checkArgument()
checkArgument(age >= 0, "年齢は0以上である必要があります");
IllegalArgumentException を簡潔に投げたいときに便利です。
ひとつの習慣:「引数は契約」だと考えてみる
メソッドは“こういう引数を渡してくれたら、こう動きますよ”という契約。
その契約を守ってもらうために、受け取る側も条件を明示する責任があるのです。
だからこそ、IllegalArgumentException を適切に使うことで、
- 「契約違反を明示的に伝える」
- 「使い方を間違えていることにすぐ気づいてもらえる」
という、双方にとって嬉しいコード設計が実現できます。
この章のまとめ
- バリデーションは“例外を防ぐ第一歩”。想定してない値が来る前提でコードを書く習慣が大切
- 呼び出し側 or 受け取る側、どこで守るかをシーンに応じて選ぶ
- 引数チェックは“契約を守る手段”。コードの安心感を生む大切な一手
- 標準APIやGuavaなども活用して、簡潔&読みやすい例外処理を身につけよう
“受け取り方”を設計する
――引数は契約である
「引数=ただの値の受け渡し」ではない
プログラムを書き始めた頃、私の中では“引数”は「処理に必要な材料」くらいの感覚でした。
でも IllegalArgumentException に出会ってから、だんだんと意識が変わってきました。
引数とは、そのメソッドが“どんな値を受け取って、どう振る舞うか”を決める契約そのもの なのだと。
それに気づいてから、設計に対する考え方がグッと深くなった気がします。
メソッドは“信じられるもの”でありたい
呼び出す側から見て、「このメソッド、変な値を渡したら爆発しちゃうかも…」と思いながら使うのは、怖いですよね。
だからこそ開発者としては、「正しい引数を渡せば、絶対に期待通り動いてくれる」メソッドを目指すのが理想です。
そのためには…
- 受け取ってもいい値の範囲を明確にする
- それをコード上でちゃんと伝える
- それでも間違った値が来たら、迷わず断る
という姿勢がとても大切になります。
“どう断るか”で信頼が生まれる
IllegalArgumentException は、単なるエラーではありません。
それを使うことで、「あなたの使い方、ちょっと違うかも」とはっきり伝える手段にもなるのです。
public void setSpeed(int kmh) {
if (kmh < 0 || kmh > 300) {
throw new IllegalArgumentException("スピードは0〜300km/hの範囲で指定してください");
}
this.speed = kmh;
}
こんなふうに書かれていたら、呼び出し側も安心ですよね。
設計で伝える“意図”
- メソッド名に目的を込める: setPositiveAmount() など、どういう値を期待しているかを名前でも伝える
- ドキュメントに条件を書く: 「このメソッドはnullや空文字は受け付けません」と明記する(Javadoc等)
- メソッドの責任を明確にする: 呼び出し側に検証を委ねるのか、内部で防御するのかをチーム内で揃える
メソッド設計のチェックポイント
項目 | 意味 |
---|---|
渡してはいけない値が明確か? | 条件や上限・下限をはっきりさせる |
不正な値が来たらちゃんとエラーにしているか? | サイレント失敗はバグの元 |
呼び出し側が使いやすい名前・仕様になっているか? | メソッド名・引数の設計で伝える努力を |
エラーメッセージは意味が通じるか? | 未来の自分&チームへのメッセージです |
この章のまとめ
- 引数は“ただの値”ではなく、呼び出し側との約束=契約
- IllegalArgumentException を上手に使えば、「想定外の値は受け取りません」という強い意思表示ができる
- コードとドキュメントで「どう使ってほしいか」を伝えることが、安心して使える設計につながる
まとめ
――引数って、思ったより深かった
怒られたことを、ちょっと感謝してみる
IllegalArgumentException に出会ったとき、最初は「えっ…ちゃんと値渡してるのに、なんで?」と困惑しました。
でもそのエラーは、「それ、たしかに型は合ってるけど…この中身じゃ動かないよ」と教えてくれるサインだったんですよね。
今になって思えば、「ただの引数」と思っていたものが、設計上の意図や契約の表現であることに気づくきっかけをくれた存在でした。
値を渡す。それはメッセージを伝えることでもある
引数とは、単に処理の材料ではなく 「私はこの前提で使います」「こういう動きを期待してます」という“会話のはじまり”でもある
その対話の中で、IllegalArgumentException は「うん、それはちょっと話が合わないかな」と伝えてくれる大事なツッコミ役です。
怖がる必要なんて、なかったんですよね。
エラーは育ててくれる
今回の記事を通じて、私は以下のことを改めて感じました。
- 正しい型でも“正しい値”とは限らない
- 引数は設計の一部であり、メソッドの契約そのもの
- “安全に壊れる”ためのバリデーションは、やさしさの表れ
- IllegalArgumentException は、“受け取る責任”の象徴
最後に:安心して受け取り、安心して断れるコードへ
きっとこれからも、思いがけない入力や「えっ、それアリ?」みたいな値と向き合う機会があるはずです。
でも、今回のように引数としっかり対話できれば、「動くだけじゃない、納得感のあるコード」に近づいていける気がします。
焦らなくていい。少しずつ、丁寧に。 あなたのコードも、私のコードも、これからもっと信頼される存在になっていけますように。

初めて IllegalArgumentException
に出会ったとき、「こわっ」と本気で思いました。 でもそこから少しずつ、エラーを通して考える力が育ってきた気がします。
記事を通じて、そんな“ちょっとずつ仲良くなっていく感じ”が、誰かの心に届いていたら嬉しいです。
コメント