Javaのthrowとは?throwsとの違いと使い方を完全解説
CONTENTS
Javaの例外処理の前提を押さえよう

Javaのthrowとthrowsを正しく理解するには、まず「例外とは何か」を押さえる必要があります。
例外処理は単なるエラー表示ではなく、異常が起きた事実と原因を呼び出し元に伝えるための仕組みです。
Javaでは問題が発生すると、例外オブジェクトが生成され、通常の処理フローから外れます。
このとき、スタックトレースによって「どこで・どんな経路で」問題が起きたかが保持されます。
例外クラスは次の階層構造を持っています。
- Throwable
- Error
- Exception
Errorは、OutOfMemoryErrorのようにアプリケーション側で回復が難しい致命的な問題を表します。
一方、Exceptionは入力不正やファイル未存在など、設計次第で対処可能な問題を表します。
実務で扱うのは、ほとんどがException側です。
例外クラスの型は「何が起きたか」を意味として表すため、適切な型を選ぶことが設計の第一歩になります。
throwとは何か?役割とできること

throwは、メソッド内で例外を明示的に発生させるための文です。
「このまま処理を続けると正しい結果にならない」と判断した地点で使います。
throwを使うことで、正常系と異常系の処理を明確に分離できます。
戻り値でエラーコードを返す設計よりも、コードの可読性と保守性が高くなります。
throwの基本構文
throw new IllegalArgumentException("message");
throwの右側には、必ず例外オブジェクトを指定します。
多くの場合、newで生成し、原因を短く説明するメッセージを渡します。
入力チェックでの使用例
public void register (String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("name must be blank");
}
// 正常処理
}
引数が不正な時点で例外を投げると、
それ以降の処理は「nameは妥当である」という前提で書けます。
throwで起きやすいミスと注意点
throwは便利ですが、使い方を誤るとコンパイルエラーや設計ミスにつながります。
到達不能コード
throw new RuntimeException();
System.out.prinln("ここは到達しない");
throwが実行された時点で処理は中断されるため、
後続の文は到達不能コードとなり、コンパイルエラーになります。
必ず例外が投げられる条件設計
条件式の誤りにより、
「正常に通る入力が存在しない」メソッドになることがあります。
ガード節を書くときは、
正常ケースが必ず存在するかを意識することが重要です。
throwsとは何か?役割と設計上の意味

throwsは、そのメソッドが特定の例外を投げる可能性があることを宣言する仕組みです。
throwのように例外を発生させる文ではありません。
throwsを書くことで、
「この例外の扱いは呼び出し側で判断してください」という契約を示します。
throwsが特に重要なのは、チェック例外です。
チェック例外は、捕捉するかthrowsで宣言することがコンパイル時に強制されます。
API設計では、throwsに何を書くかが利用者体験に直結します。
広すぎる例外を宣言すると、利用者は適切な分岐ができません。
throwsを使った設計に関して、こちらもぜひご参考ください!
throwsの基本構文と使い方
基本構文
public void readFile() throws IOException {
// 処理
}
複数の例外を宣言する場合は、カンマ区切りで列挙します。
public void process() throw IOException, SQLException {
}
オーバーライド時の制約
子クラスのメソッドは、
親クラスが宣言していないより広いチェック例外を追加できません。
これは、親型で呼び出す利用者を驚かせないためのルールです。
try-catchとthrowsの使い分け判断
例外処理で迷いやすいのが、
「ここでcatchするか、throwsで上に投げるか」という判断です。
try-catchが向くケース
- その場で回復できる
- 代替処理や再入力が可能
- ログを出して処理を継続できる
throwsが向くケース
- 上位の文脈で判断すべき
- UIやAPI層で振る舞いが変わる
- ジョブ全体の失敗として扱いたい
実務では、
境界(画面・API・バッチ起点)で例外を握る設計にすると迷いが減ります。
ここまで読んで、
「throwとthrowsの違いは分かったけれど、実際にコードを書くと迷いそう」
と感じた方もいるかもしれません。
例外処理は、読むだけではなかなか身につかず、
実際にコードを書いて、投げて、捕まえてみることで
ようやく感覚が掴める分野です。
もし今、
・環境構築でつまずいて学習が止まりがち
・try-catchやthrowを試したいが準備が面倒
・ブラウザですぐ動かしながら理解したい
という状態であれば、
ブラウザ完結型の学習コンテンツ 「ZeroCodePlus」を
一度触ってみるのもおすすめです。
ZeroCodePlusは、Progateのように
インストール不要・環境構築なしで
その場でJavaコードを書いて実行できます。
throwやthrowsも、
「この条件で例外を投げるとどうなるか」
「catchしないとどう伝播するか」
といった挙動を、手を動かしながら確認できます。
▶ ZeroCodePlusでJavaの例外処理を実際に書いて試してみる
チェック例外と非チェック例外の考え方

チェック例外(checked)
- IOException
- SQLException
外部要因で失敗し得る処理に使われます。
呼び出し側に例外処理を意識させたい場合に有効です。
非チェック例外(unchecked)
- IllegalArgumentException
- NullPointerException
プログラムの前提違反を示す用途が中心です。
正しい使い方をしていれば起きない、という位置づけになります。
例外を増やしすぎると、
呼び出し側に処理負担が連鎖するため注意が必要です。
複数例外・try-catch-finallyとの組み合わせ
複数の例外をcatchする場合は、
具体的な例外を先に書くのが基本です。
try {
// 処理
} catch (IOException e) {
} catch (Exception e) {
}
親クラスの例外を先に書くと、
後続のcatchは到達不能になります。
finallyは、例外の有無に関わらず実行される後処理に使います。
リソース解放にはtry-with-resourcesを優先すると安全です。
throw / throwsの使い分けまとめ
- throw:例外をその場で発生させる
- throws:例外を投げる可能性を宣言する
回復できるならtry-catch、
上位の判断が必要ならthrowsで伝播させます。
例外型はできるだけ具体的にし、
メッセージとスタックトレースで原因が追える設計にすると、
保守性の高いJavaコードになります。
throwやthrowsは、「Javaの文法」として覚えるだけでなく、
例外がどう流れ、どこで止まり、誰が責任を持つのか
という設計の考え方とセットで理解することが重要です。
その感覚を身につけるには、実際にコードを書いて動かし、
例外の挙動を何度も確認するのが一番の近道です。
もし今、
・独学でJavaを勉強している
・環境構築が原因で手が止まっている
・実務を意識した学習に切り替えたい
という状況であれば、
完全ブラウザ完結型の ZeroCodePlus は
学習を前に進めるきっかけになります。
読む → 書く → 動かす
このサイクルを回しながら、例外処理の理解を一段深めてみてください!