今日一日で何度もNullPointerExceptionが出ました。原因の場所によっては、ブラウザにスタックトレースが出力されたり、ブラウザは白紙でログファイルに出ていたりする。

そもそも、なんでぬるぽ(NullPointerException)が出るのだろうか???

例えば、『null.execute();』みたいなコーディングをしてもコンパイルエラーとなる。つまり、コンパイル時には見つからないからランタイムエラーとなるわけだが、これがまた嫌らしい。特にデバッグトレース内でぬるぽなんていうのは最悪である。

簡単なクラスの例として、Point { int x; int y };があるとする。メソッドはgetter, setterとtoString()とtoDebugString()とする。

デバッグログ出力メソッドがlog(String msg)として用意されていたとき、Point pt = new Point();で生成されたインスタンスをlog(pt);のように渡すとコンパイルエラーとなる。

そこで、明示的にStringに変換するわけですが、「log("" + pt);」や「log(pt.toString());」みたいにする。前者では、空文字列との連結時に暗黙的にptがStringに変換されて、結果的にptをStringに変換してメソッドに渡している。後者では、明示的にtoStringを呼んでStringに変換している。

ここで、ptがnullだった場合、前者はセーフ(nullという文字列が出力される)だが、後者はアウト(ぬるぽ発生)となる。

それでは、前者のスタイルに統一すればいいだろうと思うわけだが、冒頭でtoDebugStringメソッドがあると書きました。つまり、デバッグ出力用はtoStringではなくtoDebugString()を使うつもりということです。これではnullチェックしないとぬるぽになります。

一言でnullチェックと言っても、これが大変なんです。例えば、「pt1.toDebugString() + ", " + pt2.toDebugString() + ", " + pt3.toDebugString()」とやりたいと思ったら、やはりStringBufferを用意して一つづつnullチェックしながらappendしていくしかありません。

・・・

ここからが空想上のお話です。

まずnullは特定のクラスを持っていません。つまり、nullにどんなメソッドを呼び出してもぬるぽになります。そこで、Point pt = null;の時のptに入っているnullは、「Pointクラスのnullインスタンス」として(VMが)判断できないでしょうか。まずこれが1つ。

次にnullインスタンスに対しての特殊なメソッドをオーバーロードもしくはオーバーライドできないかな?ということです。例えば今回のpt.toDebugString();の場合、ptがPointクラスのnullインスタンスの場合では、ぬるぽを投げるのではなく"null"を返すみたいな。

となると、もっとも基底のObject.toString()も同様になります。既存ではobj=nullのときに、objは"null"なのに、obj.toString();は例外が投げられるということが、同じように"null"を返すことができるようになります。

toStringだけでなく、equalsやhashCodeなんかも同じ仕組みができるといいと思うんですけど、こんなことを考えるのは私一人でしょうか???




ブックマークに追加する