UnsupportedOperationExceptionが発生するので、逆コンパイルしたらunmodifiableだった


JavaのUnsupportedOperationExceptionの話です。

先日、とあるAPI経由で受け取ったSetを変更しようと思いました。

public void something(HogeClass hoge){
  Set<Fuga> set = hoge.getFugas();
  set.clear();
}

以下の例外が発生しました。EclipseのPluginだったのでスタックトレースが完全に出力されず・・・。以下のようなしょぼいメッセージだけでした。

Unexpected error while running Piyo java.lang.UnsupportedOperationException

なんでなんだ・・・。少し考えて自分の知識と経験から以下のいずれかだろうなーと推測しました。

  • 受け取ったSetが特殊でclearをサポート外としている。つまり、clear内でthrow new UnsupportedOperationExceptionをしている。
  • 変更不可能なSet

上記のgetFugas()メソッドの中を見ると原因が分かりました。

/**
 * @return Returns the fugas.
 */
public Set<Fuga> getFugas() {
    return Collections.unmodifiableSet(fugas);
}

unmodifiableかいっ・・・!

残念です。自分がこのクラスを際どい使い方してるのは承知してますが、それでも折角Javadocコメントが存在するんだから、ちゃんとドキュメント化しておいてほしいというものです。コレクションをコピーして返すか、変更不可として返すかする場合はドキュメント化必須でしょう。

ちなみに今回はスタックトレースが完全に表示されませんでしたが、通常は(コンソールに出力可能な状態では)以下のようなメッセージが表示されます。

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableCollection.clear(Collections.java:1094)
    at com.tsukaby.sample.Main.main(Main2.java:16)

unmodifiableSetはCollections$UnmodifiableCollectionを返却します。これを知らなかったとしてもスタックトレースから「あれ、Unmodifiable?なんだこれ・・・?HashSetとかじゃないぞ?」ときっかけを得ることくらいはできます。

スタックトレースが全部出ないことも問題ですが、貧弱なAPIドキュメントも問題だと思いました。