簡體   English   中英

將通用類型類方法作為參數傳遞

[英]Pass generic type class method as parameter

有什么方法可以將通用類型的方法作為參數傳遞? 我試圖實現的是這樣的:

ListUtils.mapObjectToField( entries, Contact.getZipCode );

我傳遞了List<T>和泛型T 到目前為止,我對通用List很好,但是我無法實現方法調用。

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 min SDK 14編碼。

最好的方法可能是像Java 8中的Stream.map一樣實現它,並提供自己的接口(也許稱為Mapper ,但是要在調用站點提供實現,則必須使用匿名內部類。 Lambda更好。

它可能看起來像這樣:

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

ListUtils會這樣:

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;
    }
}

您可以這樣稱呼它:

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

您可以在其他位置定義映射器,這將稍微清理外觀,但不會像使用lambda那樣好。

如果您想使用反射,就可以這樣做(但不建議這樣做),

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;
    }

您也可以在Android SDK 14中使用Retrolambda來獲取lambda和方法引用。

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);
  }


}

如果想進一步使用Streams ,可以在Android上使用以下庫: https : //github.com/aNNiMON/Lightweight-Stream-API

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM