関数型インターフェースで実行する Fieldgetter

昨日、Fieldsettter のことを書いたので、
Fieldsetter は、public でも private でも使用できる - Oboe吹きプログラマの黙示録

それならば、getter も同様に書いてみた。

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.function.Function;
/**
 * Fieldgetter
 */
@FunctionalInterface
public interface Fieldgetter<T, R> extends Serializable{
   String get(T t) throws Exception;

   @SuppressWarnings("unchecked")
   static <T, R> Function<T, R> of(Fieldgetter<T, R> f){
      return t->{
         try{
            Field field = t.getClass().getDeclaredField(f.get(t));
            field.setAccessible(true);
            return (R)field.get(t);
         }catch(Throwable ex){
            throw new RuntimeException(ex);
         }
      };
   }
}

例えば、以下のクラス、、、

public class Foo{
   private String name;
   private String info;
   private LocalDate date;
}
public class FooWrap{
   private Foo foo;
   public Foo getFoo() {
      return foo;
   }
}

インスタンス生成

Foo foo = GenericBuilder.of(Foo::new).with(Fieldsetter.of((t, u)->"name"), "abc")
      .with(Fieldsetter.of((t, u)->"info"), "Information")
      .with(Fieldsetter.of((t, u)->"date"), LocalDate.now())
      .build();
FooWrap fw = GenericBuilder.of(FooWrap::new).with(Fieldsetter.of((t, u)->"foo"), foo).build();

本題、Fieldgetter でクラスのフィールドの値を取り出す。

String info = Optional.ofNullable(fw)
            .map(e->Fieldgetter.of(t->"foo").apply(e))
            .map(e->(String)Fieldgetter.of(t->"info").apply(e))
            .orElse("this is null");

String name = Optional.ofNullable(fw)
            .map(e->Fieldgetter.of(t->"foo").apply(e))
            .map(e->(String)Fieldgetter.of(t->"name").apply(e))
            .orElse("this is null");

LocalDate date = Optional.ofNullable(fw)
               .map(e->Fieldgetter.of(t->"foo").apply(e))
               .map(e->(LocalDate)Fieldgetter.of(t->"date").apply(e))
               .orElse(null);

Type-safety というわけでもないし、こんなの役に立つわけないかも。。。
わざわざこんなもの。。。と思ったけど、いつかどこかで使い道あるかもしれない、、
でも、まだ思いつかない。。。


それに単に、インスタンスに格納されたフィールド値を get するだけなら、
以下の static メソッドでも充分なはずだし。。。

public static <T, R> R getValue(T t, String s){
   try{
      Field f = t.getClass().getDeclaredField(s);
      f.setAccessible(true);
      return (R)f.get(t);
   }catch(Throwable ex){
      throw new RuntimeException(ex);
   }
}