繁体   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