gpt4 book ai didi

java - 在运行时构造一个函数

转载 作者:行者123 更新时间:2023-12-03 00:06:10 25 4
gpt4 key购买 nike

是否可以使用反射从 String 创建 java.util.function.Function ?我似乎无法找到一种方法来做到这一点,因为没有 Function 的构造函数。

所以说我有这个方法:

public Integer hello() {
return 5;
}

我想获取 hello() 方法的 Function 引用。我需要传递方法的名称(在本例中为“hello”)并获取 Function

我也可以通过这种方式获取FunctionTest::hello,但我想做一些类似Test::"hello"

<小时/>

@immibis 提到尝试这个:

private Function<Test, Integer> getFunction(String s){
return (Test o) -> s;
} ^

但不幸的是,当像这样调用它时,这个方法不起作用,getFunction("hello")。 IntelliJ IDEA 给我这个错误消息:

Bad return type in lambda expression: String cannot be converted to Integer
<小时/>

不是 this 的重复项,我不需要 Method 响应,而是需要 Function 响应。

最佳答案

直观上,我们已经为我们通常编写的函数(方法)注入(inject)了很多活力:我们使用各种条件分支和循环。如果您知道如何限制可以完成的操作,则可以使用这些简单的构造来构建您的函数。

但是,从您的问题中并不清楚您到底期望什么活力:

  1. 实际的java编码
  2. 计算简单表达式,如 1+2*(4-8)
  3. 或其他一些您想要解析和评估的脚本之类的构造

对于实际的 Java 编码,我建议使用 API/SPI 对来实现某种抽象。 SPI 是一个服务提供者接口(interface),或者是一个抽象,允许其他人提供现成的和编译的类作为扩展。我相信 OSGI 提供了执行此操作的标准方法。

为了计算表达式,有许多可用的第三方库。我开发了一个,但不会提及,因为还有很多其他可用。该委员会的目的不是提出一种超越命令的工具。您还可以考虑 Nashorn,它是一个 JavaScript 引擎。

要真正允许脚本编写,我建议坚持使用 javascript 并使用 Nashorn 。 Java 允许使用插件,实际上使您能够添加额外的脚本引擎作为 JSR-223 的一部分.

[更新]

根据您的说明和示例,是的,我们需要使用某种类型的反射。

在您的情况下,您想要懒惰地决定要应用该方法到哪个类或实例。这限制了我提供如下解决方案,但是我通过优化一种情况的实现更进一步:其中功能对象的实例类将被应用或可以被预先确定。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;

public class Play {
public int hello() {
return 5;
}

static public int byebye() {
return -1;
}

public static class ExtendedPlay extends Play {
@Override
public int hello() {
return 10;
}
}

private static <T> Function<T,Integer> getFunction(Class<T> clazz,String method) throws NoSuchMethodException {
Method m = clazz.getDeclaredMethod(method);
return (o)->{
try {
return ((Integer)m.invoke(o));
} catch (IllegalAccessException | InvocationTargetException ex) {
// Just hope and pray this will be all ok!
}
return 0;
};
}

private static <T> Function<Class<T>,Integer> getStaticFunction(Class<T> clazz,String method) throws NoSuchMethodException {
Method m = clazz.getDeclaredMethod(method);
return (o)->{
try {
return ((Integer)m.invoke(o));
} catch (IllegalAccessException | InvocationTargetException ex) {
// Just hope and pray this will be all ok!
}
return 0;
};
}

private static Function<Object,Integer> getFunction(String method) {
return (o)->{
try {
Method m;
if (o instanceof Class) // For static methods
m = ((Class)o).getDeclaredMethod(method);
else // For instance methods
m = o.getClass().getDeclaredMethod(method);
return ((Integer)m.invoke(o));
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
// Just hope and pray this will be all ok!
}
return 0;
};
}

public static void main(String args[]) throws NoSuchMethodException {
// Little quicker because class type and Method instance can be resolved before multiple executions.
// Method is cached and has better compile-time type checking, but requires extra paramter.
Function<Play,Integer> f1 = getFunction(Play.class,"hello");
Function<Class<Play>,Integer> f2 = getStaticFunction(Play.class,"byebye");

// Little slower, because method instance has to be resolved for each subsequent call
// of the dereferenced Function Object. Slower but use is simpler: one less parameter, and works for
// both static and instance methods.
Function<Object,Integer> f3 = getFunction("hello");

System.out.println("Value1 is: "+f1.apply(new ExtendedPlay()));
System.out.println("Value2 is: "+f2.apply(Play.class));
System.out.println("Value3 is: "+f3.apply(new Play()));
}
}

请注意,我制定的解决方案既适用于静态方法,也适用于实例方法。

关于java - 在运行时构造一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31443125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com