2017-03-24 22 views
0

ジェネリック型のメソッドをパラメータとして渡す方法はありますか? 私は何を達成しようとすると、このようなものです:ジェネリック型のクラスメソッドをパラメータとして渡す

ListUtils.mapObjectToField(entries, Contact.getZipCode); 

私はList<T>とジェネリッククラスTからメソッドを渡します。 これまでのところ、ジェネリックリストは問題ありませんが、メソッド呼び出しを行うことはできません。

public static <T, U> List<U> mapObjectToField(List<T>elements, /*generic method*/) 
{ 
    List<U> result = new ArrayList<>(); 

    for (T current : elements) 
    { 
     result.add(current./*generic method*/); 
    } 
    return result; 
} 

ないのJava 8私はAndroidの分SDK 14

+0

あなたは文字列としてメソッドの名前を渡された場合は、反射でそれを行うことができますがかわいそうだろう。 –

+0

他の場所で実行される実際のコードを実装すると、なぜこのメソッドが必要なのですか? –

+0

java.util.function.Function を見てみることをお勧めします。 – Wietlol

答えて

0

をコードしていて、おそらく最良の方法は、Java 8でStream.mapのようにそれを実装して、独自のインタフェースを提供し、おそらくMapperと呼ばれるが、それにすることですコールサイトでの実装を提供するには、匿名の内部クラスを使用する必要があります。ラムダははるかに良いです。

それは次のようになります。

public class ListUtils { 
    public static List<U> mapObjectToField(List<T> elements, Mapper<T, U> mapper) { 
     List<U> result = new ArrayList<>(); 
     for (T current : elements) { 
      result.add(mapper.map(current)); 
     } 
     return result; 
    } 
} 

そして、あなたはこのようにそれを呼び出すことができます:

public interface Mapper<T, U> { 
    U map(T t); 
} 

ListUtilsがこれを希望あなたが他の場所でマッパーを定義することができ

List<String> zipCodes = ListUtils.mapObjectToField(contacts, 
    new Mapper<Contact, String>() { 
     public String map(Contact contact) { 
      return contact.getZipCode(); 
     } 
    }); 

これはいくらか外観をきれいにしますが、lambdaを持つほどうまくありません。

+1

それは本当に方法を渡すための質問に答えるわけではありませんが、それは私が達成しようとしていたものです。とてもありがとう! – redead

0

あなたはリフレクションを使用したい場合は、単に次のように行います(しかし、それは解決策を推奨されません)、

public static <T, U> List<U> mapObjectToField(List<T>elements, String methodName) 
    { 
     List<U> result = new ArrayList<>(); 
     Method method = null; 

     for (T current : elements) 
     { 
      if(method == null){ 
       try { 
        method = current.getClass().getDeclaredMethod(methodName); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 

      U object = (U) invokeMethod(current, method); 
      result.add(object); 
     } 
     return result; 
    } 


public static Object invokeMethod(Object obj , Method method) 
    { 
     if (method != null) { 
      try { 
       Object value = method.invoke(obj); 
       return value; 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     return null; 
    } 
0

あなたは14

アンドロイドSDKにもラムダとメソッドの参照を持っている Retrolambdaを使用することができます

https://github.com/evant/gradle-retrolambda

https://stackoverflow.com/a/42996933/802034で提案されているコードがなります:

public void main(){ 
    List<Integer> lengths = mapObjectToField(nCopies(5, "hello"), String::length); 
    } 

    public static <T, U> List<U> mapObjectToField(List<T> elements, Mapper<T, U> mapper) { 
    List<U> result = new ArrayList<>(); 
    for (T current : elements) { 
     result.add(mapper.map(current)); 
    } 
    return result; 
    } 

    public interface Mapper<T, U> { 
    U map(T t); 
    } 


} 

あなたはさらに行くとストリームを使用し、することができます。このライブラリとアンドロイドにしたい場合:https://github.com/aNNiMON/Lightweight-Stream-API

List<Integer> lengths = 
     Stream.of(nCopies(5, "hello")) 
       .map(String::length) 
       .collect(Collectors.toList()); 
関連する問題