模拟函数指针

时间:2013-03-31 20:15:45

标签: java callback

以下类包含一个应使用回调技术计算积分的方法。

package integrals;

import java.lang.*;

public class Integrals 
{
    public static double f1(double x)
    {
        return x*5+Math.sin(x);
    }   

    public static double f2(double x)
    {
        return Math.pow(x*f1(-x),x);      
    }        

    public static double TrapezoidalIntegration(double a,double b,int n,double (*f)(double))
    {
        double rValue=0;
        double dx;

        dx=(b-a)/n;

        for(double i=f(a);i<f(b);i+=dx)
            rValue+=((f(i)+f(i+dx))*dx)/2.0;

        return rValue;
    }        

    public static void main(String[] args) 
    {


    }
}

在这种情况下如何进行回调?由于它的复杂性和丑陋性,我宁愿避免使用☞such solution☜。即使它是最不痛苦的,我也不知道如何在这里实现它。

2 个答案:

答案 0 :(得分:5)

  

在这种情况下如何进行回调?由于它的复杂性和丑陋性,我宁愿避免使用such solution。即使它是最不痛苦的,我也不知道如何在这里实现它。

由于Java中没有函数指针,因此您必须使用通用接口。然后,您的功能必须是该接口的实现。是否要为实现类(即class F1 extends Function { … })或匿名类(即new Function { … })使用名称取决于您。您是否在该类中编写impollementation,或者让类实现调用您现有的静态函数之一,也取决于您。

举一个例子,使用直接包含实现的匿名类:

public class Integrals 
{

    public interface Function {
        double eval(double x);
    }

    public static final Function f1 = new Function() {
      public double eval(double x) {
        return x*5+Math.sin(x);
      }
    };

    public static final Function f2 = new Function() {
      public double eval(double x) {
        return Math.pow(x*f1.eval(-x),x);
      }
    };

    public static double TrapezoidalIntegration(double a,double b,int n,Function f)
    {
        // … using f.eval(x) to compute values

答案 1 :(得分:2)

此答案适用于不支持闭包或回调的Java 7或更低版​​本。

首先使用将计算积分值的方法定义抽象类或接口。对于此示例,我将定义一个接口:

interface IntegralCalculation {
    double getIntegralValue(double x);
}

在实际代码中,让我们替换接口的double (*f)(double)参数和要使用的方法:

public static double TrapezoidalIntegration(double a,double b,int n, IntegralCalculation integralCalc) {
    double rValue;
    double dx;

    dx=(b-a)/n;

// for(int i = f(a); i

现在,在main方法(或您将调用此TrapezoidalIntegration方法的任何其他位置)中,传递接口的实现。您可以传递实现接口匿名类的类的实例。

使用实现接口的类的类实例的示例(抱歉,不知道其他方式说出来):

class BasicFunction implements IntegralCalculation {

    @Override
    public double getIntegralValue(double x) {
        return x*5+Math.sin(x);
    }
}

public class Integrals {

    public static void main(String[] args) {
        double x = TrapezoidalIntegration(0, 10, 10, new BasicFunction());
    }
}

使用anonymous class

public class Integrals {

    public static void main(String[] args) {
        double x = TrapezoidalIntegration(0, 10, 10, new IntegralCalculation() {

            private double f1(double x) {
                return x*5+Math.sin(x);
            }

            @Override
            public double getIntegralValue(double x) {
                return Math.pow(x*f1(-x),x);
            }
        });
    }
}

从上面的代码:

  • 您无法在Java中传递函数指针,因此double (*f)(double)参数将无效,而是使用抽象类或接口。 IMO界面会更好。
  • 设计完界面后,它必须有一个满足函数指针规则的方法。在这种情况下,double (*f)(double)表示一个方法,其double作为参数并返回double。这由getIntegralValue方法处理。
  • 在接口中将函数指针替换为TrapezoidalIntegration方法中的参数后,应调用getIntegralValue,就好像它是函数指针一样:

     for(int i = integralCalc.getIntegralValue(a);
        i < integralCalc.getIntegralValue(b); i += dx) { ... }