Javaのクロージャいじってみた。(2)

4.自動でインタフェース継承
 ・型推論
  クロージャで記述すると自動的にインタフェースを継承してくれる。
  いわゆる型推論ていうの?
  いじってみた限りでは、以下の2つの記述で自動的に継承してくれる
  ことは確認した。他のケースはしらん。
    (1) 引数埋め込みで記述。
    (2) クロージャの戻り値の型を継承したいインタフェース型で記述。

  ・継承した場合メソッドはクロージャ型のinvoke()ではなく、
   各インタフェースのメソッドとして扱われる。(内部処理的にはinvoke()
   ぽいメソッドが生成されている模様。)
  ・継承(実装)できるのはインタフェースだけで、抽象クラス/クラスは
   継承できなかった。(コンパイルエラーになる)

  ソースコード

Functor<Integer> func = {Integer i => (int)(i * 2.4 + 68)};

  逆コンパイルコード

  // 呼び出し側
  obj._fld1 = _2B_INSTANCE0;


// 定義側
// 定数メンバとして定義される
public static final _cls2 _2B_INSTANCE0 = new Functor() {
// 戻り値型に継承されてる --> ~~~~~~~~~
public final int _2B_invoke(Integer integer)
{
return (int)((double)integer.intValue() * 2.39...9D + 68D);
}

    // ジェネリクスの場合、ブリッジメソッドもちゃんと生成されてる。
public final Integer calc(Integer integer)
{
return Integer.valueOf(_2B_invoke(integer));
}

public volatile Object calc(Object obj)
{
return calc((Integer)obj);
}
}

  ・(1)(2)のように直接記述することはできるが、一旦クロージャ型で
   受け取ったものを、各インタフェース型の変数/引数に渡すことは
   できない。
例:
こんな定義インタフェースと利用処理があるとする。

  public interface Closure<T> {
    public void apply(T t);
  }

  public class Loop {
    public static <T> void foreach(List<T> list, Closure<T> closure) {
      ...
    }
  }

以下のような書き方は代入の場所でエラー。

  {String=>} println = {String str => System.out.println(str) };

  // ×
  Closure<string> closure = println;
  // ×
  Loop.foreach(list, println);

このときは {String=>}型 ではなく Closure<String>型 よこせ
というコンパイルエラーが出る。
以下のような書き方はOK。

  // ○
  Closure<string> = {String str => System.out.println(str) };
  // ○
  Loop.foreach(list, {String str => System.out.println(str) });

 
 

コメント

このブログの人気の投稿

リフレクション無しにjar間のクラスを解決する作りこみ

日食ツアーその後

Javaのクロージャをいじってみた。(1)