如果您追求简洁而非性能,自Java 1.4以来有Expression
和Statement
。
Object obj="example";
String methodName="substring";
Object[] arg={ 2, 5 };
try {
Object result=new Expression(obj, methodName, arg).getValue();
new Statement(System.out, "println", new Object[]{ result }).execute();
} catch (Exception ex) {
Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ex);
}
但是,如果你想在标准功能接口,不允许checked异常的情况下使用它们,异常处理将主导源代码。
可以即使在Java 7中结合一个反射性获取方法将一个功能接口:
Object obj="example";
String methodName="substring";
Object[] arg={ 2, 5 };
Supplier<String> s;
Consumer<String> c;
try {
MethodHandle mh=MethodHandles.insertArguments(
MethodHandles.lookup().bind(obj, methodName,
MethodType.methodType(String.class, int.class, int.class)),
0, arg);
s = MethodHandleProxies.asInterfaceInstance(Supplier.class, mh);
mh=MethodHandles.lookup().bind(System.out, "println",
MethodType.methodType(void.class, String.class));
c = MethodHandleProxies.asInterfaceInstance(Consumer.class, mh);
} catch(NoSuchMethodException | IllegalAccessException ex) {
Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ex);
return;
}
String result=s.get();
c.accept(result);
这不是短,但避免了在每个功能的评价进行反射查找。
可能更有效方法是使用在Java中8,这是在运行时lambda表达式和方法引用的后端导入的LambdaMetafactory
。
Object obj="example";
String methodName="substring";
Object[] arg={ 2, 5 };
Supplier<String> s;
Consumer<String> c;
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh=lookup.findVirtual(String.class, methodName,
MethodType.methodType(String.class, int.class, int.class));
s = (Supplier<String>)LambdaMetafactory.metafactory(lookup, "get",
mh.type().changeReturnType(Supplier.class),
MethodType.methodType(Object.class), mh, MethodType.methodType(String.class))
.getTarget().bindTo(obj).invokeWithArguments(arg);
mh=MethodHandles.lookup().findVirtual(PrintStream.class, "println",
MethodType.methodType(void.class, String.class));
c = (Consumer<String>)LambdaMetafactory.metafactory(lookup, "accept",
MethodType.methodType(Consumer.class, PrintStream.class),
MethodType.methodType(void.class, Object.class), mh,
MethodType.methodType(void.class, String.class))
.getTarget().bindTo(System.out).invokeExact();
} catch(Throwable ex) {
Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ex);
return;
}
String result=s.get();
c.accept(result);
这具有较高创作的复杂性,但由于没有技术差异不再职能的后续执行会对编译时方法引用比肩的效率。
这是一个非常罕见的情况 - Java8语法糖为此进行了优化的可能性很小。如果这在你的代码库中很常见,你可以将它移动到一个辅助方法中,然后执行'() - > Utils.invoke(obj,methodName)'。 –
@OliverCharlesworth建议做什么是唯一的方法,这可能是一个答案 – Andremoniy
@Andremoniy不仅。还有运行时代码。 – talex