greflect - a java reflection API supports generics - Wiki

greflectプロジェクトのホームページおよびドキュメント一式はこちら

The project home page and the documents are here

ここはジェネリクス対応JavaリフレクションAPIであるgreflectのプロジェクトWikiです。 ですが、事実上メモ書きページになっています。 なんでって?会社とかからでも記入できるからさ。(笑)

バージョン0.11ワーキングドラフト改訂版を公開しました。またあわせて,0.11アルファ版の実装をリリースしました。

ジェネリクスの効率的な使い方

高機能なリフレクションAPIが必要とされる理由

Javaに標準リフレクションAPIを実装したとき、 おそらく開発者には「ちょっとインタプリタ的な機能を追加してみた」 程度の認識しかなかったのではないだろうか。

2003年頃までのJavaをめぐる環境においては、 リフレクションは ニッチなテクニックとして紹介されるに止まっていたように思う。 もちろんリフレクションを内部で使用するプロジェクトもあったが、 プロジェクト個別にメリットとリスクを判断して使用するもの という感があった。

しかし2004年に依存性注入(Dependency Injection)という概念が Martin Fowlerによって提唱され、 この概念を採り入れたフレームワーク(DIコンテナフレームワーク)が エンタープライズ分野で普及していった。 リフレクションはこれらのフレームワークにおいて ワイヤリング---つまりビルディングブロックを繋げるいわば漆喰(しっくい)の役目を果たす---ツールとして、 実運用環境で多用される機能へと立場を変えていった。

しかしJava標準リフレクションAPIはいまだにインタプリタ的な機能を提供するに留まっている。 このためワイヤリングに使用するには少々機能的に問題があるのが実情だ。

Java標準リフレクションAPIの第1の欠点は,実行できるのか実行してみるまで判らないことだ。 つまり、実行に必要な条件(クラス名やパラメータの型や属性などが妥当かなど)が不十分でも 実行に先立ってそれを判定する(プリチェック)ことはできない。

(続)

static メソッドの扱いについて改訂版を出すことにしたワケ

0.11-DRAFTでstatic メソッドの扱いについて後日改訂版を出すと 宣言した背景について。

正直、static メソッドについてどう扱うべきか考慮がもれていました。

と言っても現状ではstatic メソッドも特に制限なく実行することが 可能と思われます。例えば、

 long now = api.new Invoker<Long>(
               new Param<System>(){}, "currentTimeMillis")
       {}.invoke();

と実行すればおそらく何も問題なく実行できるでしょう (ガートかけてましたが,最新ソースでは実行できるようになっています)。 それでは、satatic メソッドとinstance メソッドを同様に 区別なく実行可能な仕様としてしまえば解決だと思われるかもしれません。 実際、標準ライブラリのjava.lang.reflect.Method.invoke()は satatic メソッドもinstance メソッドも区別せず実行できる仕様になっているのだし、 そういうのもアリと言えば有りでしょう。

しかしこのような仕様に倒すことは、(実装上は問題なくても) 仕様上の矛盾を引き起こす恐れがあると判断し、採用を躊躇しています。

satatic メソッドもinstance メソッドも区別せず実行できる仕様にするとどうなるのか。 static メソッドである java.lang.Enum.valueOf() を呼び出すときの例を考えて見ましょう。

 enum MyState { SOU, UTSU, FUTSUU };
 //  :
 MyState s = api.new Invoker<MyState>(
               new Param<Enum<MyState>>(){},
               "valueOf",
               new Param<Class<MyState>>(MyState.class){},
               new Param<String>("UTSU"){})
       {}.invoke();
これがもし次のように記述されていればどうなるでしょうか。
 enum MyState { SOU, UTSU, FUTSUU };
 enum AnotherState { };
 //  :
 MyState s = api.new Invoker<MyState>(
               new Param<Enum<AnotherState>>(){},
               "valueOf",
               new Param<Class<MyState>>(MyState.class){},
               new Param<String>("UTSU"){})
       {}.invoke();

実は、この2つの挙動はまったく変わりません。 これはvalueOf() はEnumのメソッドであり、 Enum<MyState>やEnum<AnotherState>に属するわけではないからです。 (注:Javaのジェネリクスの仕様であって、例えばC#は異なる) EnumのメソッドであるのにEnum<AnotherState>とか指定できてしまう、 と言うのは不自然で気持ち悪いと思います。

修正案

 enum MyState { SOU, UTSU, FUTSUU };
 //  :
 MyState s = api.new Invoker<MyState>(
               new Param<Enum>(){},
               "valueOf",
               new Param<Class<MyState>>(MyState.class){},
               new Param<String>("UTSU"){})
       {}.invoke();
のように、型引数を記述しない場合のみstatic メソッドを実行できるようにする。

(この修正方針で最新ソースでは実行できるようになっています。)

今後のリリース案

0.11

0.11-DRAFTの品質向上版

0.2

  1. プリチェックのサポート
  2. 繰り返し実行のサポート
  3. 英語版ドキュメントの整備

0.3

  1. 文字列からParamオブジェクトを生成

ソースのダウンロード~修正のチェックインの流れ

  1. subversionとmaven2をインストール
  2. ソースのダウンロード
    1. 匿名でtrunk(最新の版)を入手するとき
        svn checkout http://svn.sourceforge.jp/svnroot/greflect/trunk/greflect
      
    2. sourceforge.jpに登録したユーザ名がyo-ziでtrunk(最新の版)を入手するとき
        svn checkout svn+ssh://yo-zi@svn.sourceforge.jp/svnroot/greflect/trunk/greflect
      
  3. ビルド
      mvn jar:jar
    
  4. プロジェクトサイトのビルド
      mvn site
    
  5. リリース時のプロジェクトサイトのビルド&配布パッケージの作成
      mvn clean site assembly:assembly
      mvn site:deploy
    
    注)assemblyは必ずsite実行後に行うこと。
  6. Eclipseでビルドするときの設定
    1. workspace下にgrelectをチェックアウト
    2. New Projectでgreflectを指定
    3. eclipseのM2_REPOという変数にmaven2リポジトリパスを設定
    4. projectのpropertiesのInfoの項、 Text File EncodingをUTF-8に設定。
    5. projectのpropertiesのJava Compilerの項、 Compiler complicate levelを5.0に設定。
    6. projectのpropertiesのJava Code Style/Code Tmpletesの項、 importで etc/mukiebi-eclipse-codetemplate.xml を読み込み。
    7. projectのpropertiesのJava Code Style/Formatterの項、 importで etc/mukiebi-eclipse-codeformat.xml を読み込み。

アナウンス文のテンプレート

ジェネリクス対応JavaリフレクションAPIであるgreflectの、バージョン0.11ワーキングドラフト改訂版を公開します。 またあわせて,0.11アルファ版の実装をリリースします。

The working draft revised edition of version 0.11 of greflect - a java reflection API supports generics - is published. And the implementation of 0.11 alpha version is released at same time.

*Version: 0.11-DRAFT
*Branch: trunk
*Revision: 134

修正点
*staticメソッドの呼び出し方法を追記しました。
*Reflectionのコンストラクタの説明を追加しました。
*ダウンロードパッケージ(full)にソースツリーを添付するようにしました。

greflectはジェネリック型の型安全性を保障しつつ高速に動作する、 新時代のJavaリフレクションライブラリです。 リフレクションによるオブジェクトの動的な連結に、 ジェネリ ック型の柔軟さを取り入れることができます。 さらにジェネリック型の型安全性(type-safety)を生かした堅牢な プログラミング環境を提供します。

greflect is a new age library of java reflection that holds type safety of generic types. And it is speedy. The flexibility of the generic type can be taken to dynamic linking of objects by the reflection. In addition, Robust-programming environments that makes the best use of type safety of the generic type is provided.

修正候補

ジェネリクス機能をサポートした→ジェネリクスをサポートした 類件見直し

The specified type 'GenericClass<Integer,String>' is not applicable for type 'GenericClass<String,Integer>'.*"メッセージの妥当性 The instance of type type 'GenericClass<String,Integer>' cannot cast to 'GenericClass<Integer,String>'."メッセージの妥当性

エラーメッセージから specified は取る。ユーザが指定したとは限らないから

catchword小さく


SourceForge.jp では、各プロジェクトごとに Wiki システムが利用できるようになりました。 このページも含め、あなたのプロジェクトに合わせて自由に書き換えてください

システムは現在継続的に開発中です。Wiki本体に関して、問題点や要望などがありましたら、 トラッカー を利用して報告お願い致します。

Wiki ってなに?という方は、 Wikipedia の「ウィキ」のページ を参考にしてください。

文法などのドキュメントは、サイドバーに標準で入っているリンクか、 SourceForge.jp プロジェクト内の Wikiガイド を 参照してください。