「//fix this/」の記事インデックス

//fix this/ Javaコードの間違いをさがせ!


このシリーズは、あなたのコーディング・スキルを試すコーナーです。毎号オラクルのJavaエバンジェリストたちが、Javaコードに関する難問を出題し、正解と解説を掲載します。是非、毎号チャレンジして貴方のコーディング能力の向上にお役立て下さい。


第3回目 (Java Magazine 2012/Jul-Augからの出題)


1. 今回のテーマ 「ConnectionPool.java」

Java Servlet Programming』の第9章にあるコード例 ConnectionPool.javaには、ちょっとしたバグがあります。このコードは何年も問題なく動いていましたが、最近、(※2012/7月時点)JDBCドライバがアップグレードされたため、動かなくなりました。



2. コード

このプール・クラスのコードの一部を次に示します。このコードの問題点を特定し、プログラム全体を再設計せずに修正してください。


  private Hashtable connections = new Hashtable();
  private void initializePool(...) ... {
    for (int i = 0; i < initialPoolSize; i++)
connections.put(getNewConnection(...), Boolean.FALSE); //false=
使用されていない
    }
  }
  public Connection getConnection() ... {
     // ...フラグがFALSEのConnectionを検索...
     connections.put(con, Boolean.TRUE);
     return con;
  }
  public void returnConnection(Connection returned) {
     connections.put(returned, Boolean.FALSE);
  }

3.正しいのはどれ?

以下のうち正しい対処方法はどれでしょうか?

1) Connectionの使用をやめ、代わりにPooledConnectionを使う

2) Hashtableの使用をやめ、代わりにMapインタフェースの別の実装を使う

3) 問題のあるConnection実装を拡張し、いくつかのメソッドをオーバーライドする

4) 問題のあるConnectionをラップするようなConnectionの実装を作成する

<ヒント>
このプール・クラスのバグは、並行処理に関するものではありません。






【答え】

正解は4)です。ConnectionPool.javaコードでは、hashCode()とequals()はオーバーライドされないという誤った仮定をしていました。このため、新しいドライバへアップグレードすることで、プログラムが壊れてしまったのです。


新しい実装では、デフォルトの参照型等価の代わりに、オブジェクト等価を使用してequals()が実装されたためです。4)の方法では、プログラムをhashCode()およびequals()の実装から完全に独立させることができます。解決策は、実際のConnection実装をラップし、内部でコールをルーティングするConnectionインタフェースの実装を安全に作成することです。それによって、プログラムは常にオブジェクトの信頼性の高いhashCode()およびequals()メソッドを使用することになるでしょう。


<< 第2回へ戻る I 第4回へ進む >>

「//fix this/」の記事インデックス