一度も使ったことがない JDK 5.0 の機能について、せめてサンプル的にソースコードを書いてみた。
Java SE 6 も出たことだし……

型保証された列挙

この機能のおかげで、enum という変数名は使えなくなってしまった。
Enumerator enum = ... ってコードをよく書いていたので、Java5環境に移行すると大変。


package java5.typeofenum;
 
////////////////////////////////////////////////////////////
// Type of Enum (列挙型)
 
public enum Products { // Ref. java.lang.Enum
  BLENDED, BOOK, DVD,
}

メタデータ (注釈)

コードを堅牢にするメタデータ。
というヒント情報としての使い方をするのだと思っていたけど、
そのまま他の用途で使えたりもするらしい。


package java5.metadata;
 
public class Metadata{
 
  ////////////////////////////////////////////////////////////
  // Metadata (アノテーション)
 
  public static void doits(){
    Parent p = new Parent();
    Parent c = new Child();
    p.doit();
    c.doit();
  }
 
  public static class Parent{
    public void doit(){
      System.out.println("A parent does it.");
    }
  }
 
  public static class Child extends Parent{
    // 親クラスのメソッドをオーバーライドしていることを示すアノテーション
    @Override public void doit(){
      System.out.println("A child does it.");
    }
  }
 
}

static のインポート

static メンバにアクセスするには、そのメンバのクラスで参照を修飾する必要があります。たとえば次のようにしなければなりません。

double r = Math.cos(Math.PI * theta);

この状況を回避するため、static メンバをインタフェースに置いて、そのインタフェースから継承させることがあります。しかし、これは良い方法ではありません。実際、「Constant Interface Antipattern (不変のインタフェースアンチパターン)」であると以前から指摘され続けています。「Effective Java」の第 17 項を参照してください。問題は、クラスが別のクラスの static メンバを使用するのは、実装のほんのわずかな部分だということです。クラスがインタフェースを実装すると、そのインタフェースはそのクラスの公開 API の一部となります。実装の詳細は、公開 API として公開するべきではありません。

JDK 5.0 ドキュメント - static のインポート

Effective Java 17項 を読んだけど、なんかいまいち消化不良。

「型を定義するためだけにインターフェースを使用する」Constant Interface Antipattern (不変のインタフェースアンチパターン)。これをすると、クラスのメンバ定数を手軽にメンバ定数名だけで利用するには HogeClass implements HogeConstantInterface しなくちゃいけない。すると、そのクラス HogeClass の public なメンバ定数として他のクラスには見えてしまう。困る。

だから、interface のメンバ定数じゃなくて、(Math.PI みたいな)クラスのメンバ定数を使って、

private static final PI = Math.PI;

って書いておいて、private 定数を使え、と。

private static final PI = HogeConstantInterface.PI;

でも良いような気がするけど、
interface だと、ついうっかり implements できちゃう (もともと implements するためのものだから) ことがマズいという話なのかな。

で、ここまでは Java 5 より前の話で、
Java 5 のスタティック・インポートという新機能を使うと、クラスの static メンバを参照する際に「メンバ名」を記述するだけで良い。
もう、危なっかしい implements HogeConstantInterface よりも、こっちのほうがオススメですよ、と。

難しいことはあまり考えたくないので、
「お気ラクに定数を使える機能」ということで納得しておこう。


package java5.staticimport;
 
////////////////////////////////////////////////////////////
// Static import
 
import static java5.typeofenum.Products.*; // 列挙型のインポート
import static java5.metadata.Metadata.doits; // クラス・メソッドのインポート
 
public class StaticImport {
  
  public static void main(String[] args){
    System.out.println(BLENDED); // <--- Products.BLENDED
    System.out.println(BOOK); // <--- Products.BOOK
    System.out.println(DVD); // <--- Products.DVD
    doits(); // <--- Metadata.doits();
  }
 
}

参考

ついに JavaWorld も休刊。デザインがカッコよかったのになぁ……

tags: zlashdot Java Java

Posted by NI-Lab. (@nilab)