Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java反射:根据参数和签名自动调用正确的重载方法_Java_Reflection_Overloading - Fatal编程技术网

Java反射:根据参数和签名自动调用正确的重载方法

Java反射:根据参数和签名自动调用正确的重载方法,java,reflection,overloading,Java,Reflection,Overloading,假设您有一个名为doTask的重载方法: public class Game { void doTask(Joker joker); void doTask(Batman batman, Robin robin); } 我想调用正确的方法,给定方法的名称(“doTask”)和一组参数,这些参数的数量和类型是未知的 通常,这至少包括三个步骤: 1.找到参数的数量及其类型,并创建一个数组Class[]myTypes 2.识别正确的重载方法,即方法rightMethod=game.getCl

假设您有一个名为
doTask
的重载方法:

public class Game {
  void doTask(Joker joker);
  void doTask(Batman batman, Robin robin);
}
我想调用正确的方法,给定方法的名称(
“doTask”
)和一组参数,这些参数的数量和类型是未知的

通常,这至少包括三个步骤:
1.找到参数的数量及其类型,并创建一个数组
Class[]myTypes

2.识别正确的重载
方法,即
方法rightMethod=game.getClass().getMethod(“doTask”,myTypes)
3.调用方法:
rightMethod.Invoke(paramArray)

是否有一种工具可以要求Java反射自动识别要使用的正确重载方法,并使我们不必执行步骤1和步骤2?我认为理想情况下,这应该是:

Library.invoke(“doTask”,paramArray)

首先-回答您的问题-不,没有这样的设施

其次,步骤2有点复杂,因为它不足以从参数创建类数组并调用
getMethod

实际上,您必须迭代与名称、参数数量匹配的所有方法,并比较方法的参数类型,以确保指定参数类型(即
methodArgType.isAssignableFrom(paramType)
)的赋值兼容性,以确保正确反映方法参数类型的兼容子类型。使用varargs会让事情变得稍微复杂一些。

有这样一个设施,分别是。如果需要返回值:

Game game = new Game();
Joker joker = new Joker();
Statement st = new Statement(game, "doTask", new Object[]{ joker });
st.execute();
但是,它仅适用于
public
方法

此外,与
java.lang.reflect.Method
不同,此工具尚未调整以支持varargs参数,因此您必须手动创建参数数组

可以证明,它可以根据参数类型选择正确的目标方法,参数类型不一定与参数类型相同:

ExecutorService es = Executors.newSingleThreadExecutor();
class Foo implements Callable<String> {
    public String call() throws Exception {
        return "success";
    }
}
// has to choose between submit(Callable) and submit(Runnable)
// given a Foo instance
Expression ex = new Expression(es, "submit", new Object[]{ new Foo() });
Future<?> f = (Future<?>)ex.getValue();
System.out.println(f.get());
es.shutdown();
Executors=Executors.newSingleThreadExecutor();
类Foo实现了可调用的{
公共字符串调用()引发异常{
返回“成功”;
}
}
//必须在提交(可调用)和提交(可运行)之间进行选择
//给出一个Foo实例
表达式ex=新表达式(es,“submit”,新对象[]{new Foo()});
Future f=(Future)ex.getValue();
System.out.println(f.get());
es.shutdown();

这听起来有点不对劲。你想在这里实现什么?你为什么不知道情人的数目?你从哪里弄来的?他们有什么表格?当您不知道参数的数量时,如何确保有一个具有正确数量参数的实现?是否可以选择将参数列表直接传递给
doTask()
,并让实现决定如何处理它们?重载:带有一些最小的设计味道。反思:更大的气味。长话短说:你打算在这里解决的根本问题是什么?lupz和GhostCat,我同意你的观点,如果我从头开始写整个项目,就不会这样写。目前,已经编写了
doTask()
方法(并被其他代码使用)。我正在编写一个包装函数,
myFunc(Object…paramArray)
,带有额外的业务逻辑,以调用正确的
doTask()
。另一个选项当然是为每个重载的
doTask()
方法编写单独的包装。但是,这会复制很多业务逻辑代码,并使其难以维护。这对所有参数来说都是相同的吗?如果没有,那么您已经可以识别应该使用一个包装器方法调用哪个
doTask()
。广泛未知,@Gerald Mücke感谢您的输入。关于您对步骤2和步骤3的评论,对于步骤2,您似乎可以简单地执行以下操作:
Class[]argTypeArray=newclass[paramArray.length];对于(int n=0;n
Method rightMethod=Game.class.getMethod(“doTask”,argTypeArray”)
最后,对于第3步,
rightMethod.invoke(Game,paramArray)
。感谢您给出了详细的答案。最初我被“参数类型不一定!=参数类型”难住了,但我认为其含义是:
new Foo()
属于
Foo
(参数类型),它与
Callable
(参数类型)不同。但是由于
Foo
Callable
的子类,因此将调用右侧的
submit
。我说的对吗@Holger?另外,由于
Expression
Statement
都在bean包中,所以它们只对JavaBeans类有效,对吗?@Holger噢,该死的。。。没想到会这样exist@flow2k:对,只需调用
getMethod(“submit”,argument.getClass())将失败,因为没有
submit(Foo)
方法,因此实现必须检查每个方法的适用性,正如Gerald Mücke所阐述的那样。谢天谢地,这已经得到实施。关于“javabean”,bean模式非常广泛,几乎可以匹配所有类。唯一的限制已经在我的回答中提到了;它仅适用于
public
方法。我的示例已经证明了这一点,它使用了
ExecutorService
和内部类
Foo
,也没有任何显式操作作为javabean。