我们可以使用为 java8 的可选接口获取动态值的函数吗?

Can we use Function which takes dynamic values for optional interface for java8

我是 java 8 的新手,正在尝试动态传递方法名称以获取值。

我有一个 Request 请求,其中包含 getInput1()getInput2() 方法。我可以像这样静态映射 Optional

void methodExecute(){ 
  Optional<Request> request = Optional.of(new Request()); 
  request.map(request::getInput1); //gives input1 value
  request.map(request::getInput2); //gives input2 value 
}

如果在运行时传递 "getInput1""getInput2" 方法名称,我们可以动态地做同样的事情吗?

下面是我的做法。但是没用。

@FunctionalInterface
public interface Function_WithExceptions<T, V,R, E extends Exception> {
    R apply(T t,V v) throws E;
}

public class LambdaUtil<Input1, Input2> {
    public static <Input1,Input2, R, E extends Exception> 
                            Function_WithExceptions<Input1,Input2, R,E> rethrowFunction(Function_WithExceptions<Input1,Input2, R, E> function) throws E  {
        return (t,v) -> {
            try {
                return function.apply(t,v);
            } catch (Exception exception) {
                throwActualException(exception);
                return null;
            }
        };
    }
    @SuppressWarnings("unchecked")
    private static <E extends Exception> void throwActualException(Exception exception) throws E {
        throw (E) exception;
    }
}

public Function_WithExceptions getFunction(){
        Function_WithExceptions<Request, String,Object,Exception> requestObjParamFun = (reqObj,req)->MethodUtils.invokeExactMethod(reqObj, req);
        return requestObjParamFun;
}

如果我理解正确的话,你的问题可以这样解决:

static <T> Function<Request, T> reflect(String getterName, Class<T> resultType)
           throws NoSuchMethodException, SecurityException {
    Method method = Request.class.getMethod(getterName);
    return req -> {
        try {
            return resultType.cast(method.invoke(req));
        } catch (IllegalAccessException | IllegalArgumentException
                | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    };
}

这里我们只是使用普通反射API通过名称获取Requestclass的方法和调用它的函数return。使用示例:

// Some test Request class
static class Request {
    public String getInput1() {return "aa";}
    public Integer getInput2() {return 1;}
}

public static void main(String[] args) throws Exception {
    Optional<Request> request = Optional.of(new Request());
    System.out.println(request.map(reflect("getInput1", String.class))); // Optional[aa]
    System.out.println(request.map(reflect("getInput2", Integer.class))); // Optional[1]
}

如果您想为 getter 动态生成 Function,但又不想每次调用都诉诸反射,您可以使用与 Java 语言方法引用相同的后端:

static <T> Function<Request, T> reflect(String getterName, Class<T> resultType)
            throws ReflectiveOperationException {
    MethodHandles.Lookup l=MethodHandles.lookup();
    MethodType getter=MethodType.methodType(resultType);
    MethodHandle target = l.findVirtual(Request.class, getterName, getter);
    getter=target.type();
    try {
        return (Function)LambdaMetafactory.metafactory(l, "apply",
            MethodType.methodType(Function.class),
            getter.generic(), target, getter).getTarget().invokeExact();
    } catch(Throwable ex) {
        throw new ReflectiveOperationException(ex);
    }
}

这可以像 一样使用,但不会对 Function 调用使用反射(通常;因为它是 JRE 特定的,它如果方法引用在特定 JRE 实现中也使用反射,则可以使用反射。

但是,与反射方法一样,必须小心使用它,因为错误使用不会在编译时被发现,而是在运行时被发现。