我们可以使用为 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通过名称获取Request
class的方法和调用它的函数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 实现中也使用反射,则可以使用反射。
但是,与反射方法一样,必须小心使用它,因为错误使用不会在编译时被发现,而是在运行时被发现。
我是 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通过名称获取Request
class的方法和调用它的函数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 实现中也使用反射,则可以使用反射。
但是,与反射方法一样,必须小心使用它,因为错误使用不会在编译时被发现,而是在运行时被发现。