前回の記事では実行時例外とは何かについて書いた。
しかしもう一度 Java における例外をもう少し掘り下げ、 .NET とも比較し実行時例外について考えてみる。
コンパイラによる事前チェックが困難で実行時でないと判断ができないタイプであり、プログラムの通常ロジックにおいて回避可能な例外がこれに分類される。
たとえば、 NullPointerException、 IndexOutOfBoundsException などがある。
エラーとは Error クラスおよびその派生クラスに分類されている例外だ。
このエラーは通常いつ発生するか予期できないものであり、アプリケーション実行に深刻な影響を及ぼすタイプだ。
また、アプリケーションレベルでキャッチするようなものでもないので、コンパイル時によるチェックは行われない。
代表例としては、StackOverflowError、 ClassFormatError などがある。
検査例外とは、コンパイル時にチェックされる例外であり、 catch を強制される例外だ。
多くはプログラムの通常ロジックとは別の外的要因によって発生する例外だ。
IOException などがこれにあたる。
ほぼと書いたのは一部例外があるからだ。
これは Microsoft の設計ミスであり、そのため .NET 1.x と .NET 2.0 ではアプリケーション定義の例外に関する方針が変わっている。
.NET 1.x ではアプリケーション定義の例外は ApplicationException から派生させるというガイドラインが出ていたが、 .NET 2.0 においては Exception から直接派生するようにされている。
「プログラミング .NET Framework 」によれば、 SystemException と ApplicationException を各例外の基底型とすることにはあまり意味を感じないと書かれており、むしろ混乱するとも書かれている。
そこで、Microsoft も方針を切り替えたようだ。
ちなみに、 .NET (というより C# かな?) では Java とは違い検査例外というものがない。
私自身の経験上、コンパイル時にチェックしてくれる検査例外が欲しくなることはある。
しかし Bruce Eckel は検査例外は失敗であったと述べており、 C# のアーキテクトである Anders Hejlsberg も C# 言語への検査例外の搭載は見送った。
検査例外にはメリットもあるが、それよりもデメリットが大きい。
例えば、インターフェースで実装を切り替えるようなプログラムがあるとしよう。
スローする例外というのは、当然、実装によって大きく変わることがあり、呼び出し側はいちいち個々の実装を気にする必要が出てくる。
そのような場合、せっかくのインターフェースであるメリットをデメリットにしてしまい、全ての例外をキャッチするような愚行をしてしまう、といったことが多いようだ。
これは明らかにまずいデメリットだ。
しかし上記の Java の例外分類を見てみると、「コンパイル時にはチェックされないが、アプリケーション実行時にはチェックされる例外」という意味では Runtime を「実行時」と訳するのは、少なくとも Java においては間違いではないことになる。
Java 言語設計者達がどのようなプロセスを経て例外を三つに分けたかは私の知るところではないので、結局は Java における RuntimeException の Runtime が指す本当の意味はわからない。(Java に詳しい人、教えて)
逆に .NET Framework では上述のように例外がほぼきれいに二つに分類されているため、 Runtime Exception の Runtime は実行時というよりも、ランタイムが送出する例外ということで、 RuntimeException をランタイム例外とするのが正解で、むしろ実行時例外という用法は誤りではないかと思う。
しかしもう一度 Java における例外をもう少し掘り下げ、 .NET とも比較し実行時例外について考えてみる。
Java における例外分類
Java 言語では次のように例外を分類している。- 実行時例外 (runtime exception)
- エラー (error)
- 検査例外 (checked exception)
コンパイラによる事前チェックが困難で実行時でないと判断ができないタイプであり、プログラムの通常ロジックにおいて回避可能な例外がこれに分類される。
たとえば、 NullPointerException、 IndexOutOfBoundsException などがある。
エラーとは Error クラスおよびその派生クラスに分類されている例外だ。
このエラーは通常いつ発生するか予期できないものであり、アプリケーション実行に深刻な影響を及ぼすタイプだ。
また、アプリケーションレベルでキャッチするようなものでもないので、コンパイル時によるチェックは行われない。
代表例としては、StackOverflowError、 ClassFormatError などがある。
検査例外とは、コンパイル時にチェックされる例外であり、 catch を強制される例外だ。
多くはプログラムの通常ロジックとは別の外的要因によって発生する例外だ。
IOException などがこれにあたる。
.NET における例外分類
.NET Framework における例外の分類は主に二つにわけられる。- ランタイムが送出する例外
- アプリケーション定義の例外
ほぼと書いたのは一部例外があるからだ。
これは Microsoft の設計ミスであり、そのため .NET 1.x と .NET 2.0 ではアプリケーション定義の例外に関する方針が変わっている。
.NET 1.x ではアプリケーション定義の例外は ApplicationException から派生させるというガイドラインが出ていたが、 .NET 2.0 においては Exception から直接派生するようにされている。
「プログラミング .NET Framework 」によれば、 SystemException と ApplicationException を各例外の基底型とすることにはあまり意味を感じないと書かれており、むしろ混乱するとも書かれている。
そこで、Microsoft も方針を切り替えたようだ。
ちなみに、 .NET (というより C# かな?) では Java とは違い検査例外というものがない。
私自身の経験上、コンパイル時にチェックしてくれる検査例外が欲しくなることはある。
しかし Bruce Eckel は検査例外は失敗であったと述べており、 C# のアーキテクトである Anders Hejlsberg も C# 言語への検査例外の搭載は見送った。
検査例外にはメリットもあるが、それよりもデメリットが大きい。
例えば、インターフェースで実装を切り替えるようなプログラムがあるとしよう。
スローする例外というのは、当然、実装によって大きく変わることがあり、呼び出し側はいちいち個々の実装を気にする必要が出てくる。
そのような場合、せっかくのインターフェースであるメリットをデメリットにしてしまい、全ての例外をキャッチするような愚行をしてしまう、といったことが多いようだ。
これは明らかにまずいデメリットだ。
改めて実行時例外とは何か
前回の記事では RuntimeException の Runtime は「実行時」という意味ではないと書いた。しかし上記の Java の例外分類を見てみると、「コンパイル時にはチェックされないが、アプリケーション実行時にはチェックされる例外」という意味では Runtime を「実行時」と訳するのは、少なくとも Java においては間違いではないことになる。
Java 言語設計者達がどのようなプロセスを経て例外を三つに分けたかは私の知るところではないので、結局は Java における RuntimeException の Runtime が指す本当の意味はわからない。(Java に詳しい人、教えて)
逆に .NET Framework では上述のように例外がほぼきれいに二つに分類されているため、 Runtime Exception の Runtime は実行時というよりも、ランタイムが送出する例外ということで、 RuntimeException をランタイム例外とするのが正解で、むしろ実行時例外という用法は誤りではないかと思う。






