Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.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 - Fatal编程技术网

如何在java中动态构建函数?

如何在java中动态构建函数?,java,Java,我正在解析一个文本文件,该文件映射到一些java代码,如: public void eval(Node arg) { if(arg.data.equals("rand")) { moveRandomly(); } else if(arg.data.equals("home")) { goHome(); } else if(

我正在解析一个文本文件,该文件映射到一些java代码,如:

public void eval(Node arg)
    {
        if(arg.data.equals("rand"))
        {
            moveRandomly();
        }
        else if(arg.data.equals("home"))
        {
            goHome();
        }
            else if(arg.data.equals("iffood"))
    {
        ifFoodHere(arg.left, arg.right);
    }//snip..

这将需要重新评估大约一千次,我不希望每次都遍历整个过程。是否有任何方法可以使此遍历一次,然后使其成为每隔一次调用的函数?

创建一个匿名内部类

比如:

public Callable<Void> eval(Node arg)
{
  if(arg.data.equals("rand"))
  {
    return new Callable<Void>{ public Void call() { moveRandomly(); return null; } };
  }
  ...
}

Callable<Void> f = eval(a);
f.call();
public可调用eval(节点arg)
{
如果(参数数据等于(“兰德”))
{
返回新的可调用{public Void call(){moveRandomy();返回null;}};
}
...
}
可调用f=评估(a);
f、 call();

您可以制作Runnable地图:

Map<String, Runnable> methods = new HashMap<String, Runnable>();
methods.put("rand", new Runnable() 
{
    public void run()
    {
        moveRandomly();
    }
});
...

如果您知道可以使用的所有参数/命令,我可能会这样做:

enum Args {
  home, rand, iffood;

  private Method method;

  private Args () {
    try {
      this.method = Commands.class.getMethod(this.name(), Node.class);
    } catch (final Exception e) {}
  }
  public void invoke (final Node args)
    throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    this.method.invoke(null, args);
  }
  public static Args valueOf (final Node arg) {
    return valueOf(arg.data);
  }
  public static void eval (final Node arg)
    throws IllegalArgumentException, IllegalAccessException,
      InvocationTargetException {
    valueOf(arg).invoke(arg);
  }
}
命令实现包括:

class Commands {    
  public static void home (final Node arg) {
    goHome(); // Call the implementation
    // or simply make these bodies the implementations.
  }
  public static void iffood (final Node arg) {
    ifFoodHere(arg.left, arg.right);
  }    
  public static void rand (final Node arg) {
    moveRandom();
  }
  //...
}
然后,您的eval()变为:

try {
  Args.eval(arg);
} catch (IllegalArgumentException e) {
  // Handle unknown arg.data
}

eval函数通过子函数递归调用。这会改变它的工作方式吗?您可以调用一个callable,它是由您创建的callable中的递归eval返回的。附:听起来像绕口令。:)
java.util.concurrent.Callable
?嗯。推动进程:为一个有意义的接口编写三行代码。我没有提到“java.util.concurrent”。只是一些“可调用的”。我想你是说可调用的?如果他执行Runnable,那么每个命令都将在一个单独的线程中运行,这与原始代码的运行方式非常不同。Callable也将在一个单独的线程中运行。它返回类型为T的值;Runnable不会。如果我在一个新线程中启动Runnable,它只会在一个单独的线程中运行,对吗?你可以用任何你想要的课程。他甚至可以用一个将Node作为参数的方法创建自己的类,这样他就可以访问节点上的其他数据,因为他表示的数据可能是他想要的。@Joel-正确,Runnable和Callable都需要一个线程来启动。
Runnable
与线程相关,因为线程使用Runnable。但这并不意味着只有在使用线程时才需要使用Runnable
Runnable
只是一个接口,它有一个名为
run
的方法。亨斯:
Runnable
。无论如何,我只是把它作为一个例子。
enum方法的+1。。。但是您可以进一步简化,每个枚举可以有一个
apply(final Node arg)
方法,该方法分别为每个枚举定义。这样就不需要单独的Commands类或使用反射。
try {
  Args.eval(arg);
} catch (IllegalArgumentException e) {
  // Handle unknown arg.data
}