我有一个方法,大约有十行代码。我想创建更多的方法来做完全相同的事情,除了一个会改变一行代码的小计算。这是一个传递函数指针来替换这一行的完美应用程序,但是Java没有函数指针。我最好的选择是什么?


当前回答

好吧,这个帖子已经足够老了,所以我的回答很可能对这个问题没有帮助。但是因为这个帖子帮助我找到了我的解决方案,我还是把它放在这里。

我需要使用一个具有已知输入和已知输出(都是double)的变量静态方法。因此,知道了方法包和名称后,我可以这样工作:

java.lang.reflect.Method Function = Class.forName(String classPath).getMethod(String method, Class[] params);

对于接受一个double作为参数的函数。

在具体情况下,我用

java.lang.reflect.Method Function = Class.forName("be.qan.NN.ActivationFunctions").getMethod("sigmoid", double.class);

并在以后更复杂的情况下调用它

return (java.lang.Double)this.Function.invoke(null, args);

java.lang.Object[] args = new java.lang.Object[] {activity};
someOtherFunction() + 234 + (java.lang.Double)Function.invoke(null, args);

activity是任意的双精度值。我正在考虑可能做得更抽象和一般化一点,就像SoftwareMonkey所做的那样,但目前我对它的方式很满意。三行代码,没有必要的类和接口,还不错。

其他回答

看看lambdaj

http://code.google.com/p/lambdaj/

特别是它新的闭包特征

http://code.google.com/p/lambdaj/wiki/Closures

你会发现一种非常易读的方式来定义闭包或函数指针,而无需创建无意义的接口或使用丑陋的内部类

好吧,这个帖子已经足够老了,所以我的回答很可能对这个问题没有帮助。但是因为这个帖子帮助我找到了我的解决方案,我还是把它放在这里。

我需要使用一个具有已知输入和已知输出(都是double)的变量静态方法。因此,知道了方法包和名称后,我可以这样工作:

java.lang.reflect.Method Function = Class.forName(String classPath).getMethod(String method, Class[] params);

对于接受一个double作为参数的函数。

在具体情况下,我用

java.lang.reflect.Method Function = Class.forName("be.qan.NN.ActivationFunctions").getMethod("sigmoid", double.class);

并在以后更复杂的情况下调用它

return (java.lang.Double)this.Function.invoke(null, args);

java.lang.Object[] args = new java.lang.Object[] {activity};
someOtherFunction() + 234 + (java.lang.Double)Function.invoke(null, args);

activity是任意的双精度值。我正在考虑可能做得更抽象和一般化一点,就像SoftwareMonkey所做的那样,但目前我对它的方式很满意。三行代码,没有必要的类和接口,还不错。

如果你只有一个不同的行,你可以添加一个参数,比如一个标志和一个If (flag)语句,它调用一行或另一行。

你也可以这样做(在一些罕见的情况下是有意义的)。问题(这是一个大问题)是您失去了使用类/接口的所有类型安全性,并且您必须处理方法不存在的情况。

它确实有一个“好处”,即您可以忽略访问限制并调用私有方法(示例中没有显示,但您可以调用编译器通常不允许您调用的方法)。

同样,这在很少的情况下是有意义的,但在那些情况下,这是一个很好的工具。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class Main
{
    public static void main(final String[] argv)
        throws NoSuchMethodException,
               IllegalAccessException,
               IllegalArgumentException,
               InvocationTargetException
    {
        final String methodName;
        final Method method;
        final Main   main;

        main = new Main();

        if(argv.length == 0)
        {
            methodName = "foo";
        }
        else
        {
            methodName = "bar";
        }

        method = Main.class.getDeclaredMethod(methodName, int.class);

        main.car(method, 42);
    }

    private void foo(final int x)
    {
        System.out.println("foo: " + x);
    }

    private void bar(final int x)
    {
        System.out.println("bar: " + x);
    }

    private void car(final Method method,
                     final int    val)
        throws IllegalAccessException,
               IllegalArgumentException,
               InvocationTargetException
    {
        method.invoke(this, val);
    }
}

在没有函数数组接口的情况下做同样的事情:

class NameFuncPair
{
    public String name;                // name each func
    void   f(String x) {}              // stub gets overridden
    public NameFuncPair(String myName) { this.name = myName; }
}

public class ArrayOfFunctions
{
    public static void main(String[] args)
    {
        final A a = new A();
        final B b = new B();

        NameFuncPair[] fArray = new NameFuncPair[]
        {
            new NameFuncPair("A") { @Override void f(String x) { a.g(x); } },
            new NameFuncPair("B") { @Override void f(String x) { b.h(x); } },
        };

        // Go through the whole func list and run the func named "B"
        for (NameFuncPair fInstance : fArray)
        {
            if (fInstance.name.equals("B"))
            {
                fInstance.f(fInstance.name + "(some args)");
            }
        }
    }
}

class A { void g(String args) { System.out.println(args); } }
class B { void h(String args) { System.out.println(args); } }