Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.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_Closures_Function Pointers - Fatal编程技术网

什么';Java中最接近函数指针的替代品是什么?

什么';Java中最接近函数指针的替代品是什么?,java,closures,function-pointers,Java,Closures,Function Pointers,我有一个大约十行代码的方法。我想创建更多的方法来做完全相同的事情,除了一个小的计算,它将改变一行代码。这是传递函数指针以替换这一行的完美应用程序,但Java没有函数指针。我的最佳选择是什么?匿名内部类 假设您希望传递一个带有字符串参数的函数,该参数返回int 首先,如果不能重用现有接口,则必须定义一个接口,并将函数作为其唯一成员 interface StringFunction { int func(String param); } 采用指针的方法只接受StringFunction实例

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

匿名内部类

假设您希望传递一个带有
字符串
参数的函数,该参数返回
int

首先,如果不能重用现有接口,则必须定义一个接口,并将函数作为其唯一成员

interface StringFunction {
    int func(String param);
}
采用指针的方法只接受
StringFunction
实例,如下所示:

public void takingMethod(StringFunction sf) {
   int i = sf.func("my string");
   // do whatever ...
}
并被称为:

ref.takingMethod(new StringFunction() {
    public int func(String param) {
        // body
    }
});
编辑:在Java 8中,可以使用lambda表达式调用它:

ref.takingMethod(param -> bodyExpression);
doCalculation((i) -> i.toString(), 2);
对于每个“函数指针”,我将创建一个小指针来实现您的计算。 定义所有类都将实现的接口,并将这些对象的实例传递到更大的函数中。这是“”和“”的组合


@sblundy的例子很好。

您需要创建一个接口,提供您想要传递的功能。例如:

/**
 * A simple interface to wrap up a function of one argument.
 * 
 * @author rcreswick
 *
 */
public interface Function1<S, T> {

   /**
    * Evaluates this function on it's arguments.
    * 
    * @param a The first argument.
    * @return The result.
    */
   public S eval(T a);

}
/**
*一个简单的接口,用于封装一个参数的函数。
* 
*@author rcreswick
*
*/
公共接口功能1{
/**
*根据其参数计算此函数。
* 
*@param a是第一个参数。
*@返回结果。
*/
公众评估(TA);
}
然后,当需要传递函数时,可以实现该接口:

List<Integer> result = CollectionUtilities.map(list,
        new Function1<Integer, Integer>() {
           @Override
           public Integer eval(Integer a) {
              return a * a;
           }
        });
List result=CollectionUtilities.map(列表、,
新功能1(){
@凌驾
公共整数评估(整数a){
返回a*a;
}
});
最后,map函数使用传入的函数1,如下所示:

   public static <K,R,S,T> Map<K, R> zipWith(Function2<R,S,T> fn, 
         Map<K, S> m1, Map<K, T> m2, Map<K, R> results){
      Set<K> keySet = new HashSet<K>();
      keySet.addAll(m1.keySet());
      keySet.addAll(m2.keySet());

      results.clear();

      for (K key : keySet) {
         results.put(key, fn.eval(m1.get(key), m2.get(key)));
      }
      return results;
   }
java.lang.reflect.Method Function = Class.forName(String classPath).getMethod(String method, Class[] params);
void doCalculation(Function<Integer, String> calculation, int parameter) {
    final String result = calculation.apply(parameter);
}
公共静态地图zipWith(功能2 fn,
地图m1、地图m2、地图结果){
Set keySet=newhashset();
addAll(m1.keySet());
addAll(m2.keySet());
结果:清晰();
用于(K键:键集){
结果:put(key,fn.eval(m1.get(key),m2.get(key));
}
返回结果;
}

如果不需要传入参数,通常可以使用Runnable而不是自己的接口,或者可以使用各种其他技术使参数计数不那么“固定”,但这通常是与类型安全性的折衷。(或者您可以重写函数对象的构造函数,以便以这种方式传递参数。。有很多方法,有些方法在某些情况下工作得更好。)

您可能也有兴趣了解Java 7涉及闭包的工作:



对我来说,这听起来像是一种战略模式。查看fluffycat.com Java patterns。

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

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

同样,这是一个罕见的情况,这是有意义的,但在那些场合,这是一个很好的工具

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);
    }
}

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

当在这一行中可以进行预定义数量的不同计算时,使用枚举是实现策略模式的一种快速而清晰的方法

public enum Operation {
    PLUS {
        public double calc(double a, double b) {
            return a + b;
        }
    },
    TIMES {
        public double calc(double a, double b) {
            return a * b;
        }
    }
     ...

     public abstract double calc(double a, double b);
}
显然,策略方法声明以及每个实现的一个实例都定义在一个类/文件中。

请查看lambdaj

特别是它的新闭包特性


您将找到一种非常可读的方法来定义闭包或函数指针,而无需创建无意义的接口或使用丑陋的内部类

在Java编程时,我真正错过的事情之一是函数回调。其中一种情况是,在递归处理层次结构中,您希望对每个项目执行一些特定的操作,而这种情况下,对这些项目的需求会不断出现。比如遍历目录树,或者处理数据结构。我内心的极简主义者讨厌为每个具体情况定义接口和实现

有一天我发现自己在想为什么不呢?我们有方法指针——方法对象。通过优化JIT编译器,反射调用实际上不再带来巨大的性能损失。除了将文件从一个位置复制到另一个位置之外,反射方法调用的成本也变得微不足道

当我进一步思考时,我意识到OOP范例中的回调需要将对象和方法绑定在一起——输入回调对象


请查看我的基于反射的解决方案。免费使用。

@sblundy的答案很好,但匿名内部类有两个小缺陷,主要是它们不易重用,次要是语法庞大

好在他的模式扩展成完整的类,而主类(执行计算的那个)没有任何变化

当您实例化一个新类时,您可以将参数传递给该类,该类可以作为等式中的常量——因此,如果您的一个内部类如下所示:

f(x,y)=x*y
Function<InputType, OutputType> functionname = (inputvariablename) {
... 
return outputinstance;
}
但有时你需要一个:

f(x,y)=x*y*2
第三种可能是:

f(x,y)=x*y/2
与创建两个匿名内部类或添加“passthrough”参数不同,您可以创建一个实际类,并将其实例化为:

InnerFunc f=new InnerFunc(1.0);// for the first
calculateUsing(f);
f=new InnerFunc(2.0);// for the second
calculateUsing(f);
f=new InnerFunc(0.5);// for the third
calculateUsing(f);
它只需将常量存储在类中,并在接口中指定的方法中使用它

事实上,如果你知道的话
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);
import java.util.function.IntBinaryOperator;

class A {
    static void method(IntBinaryOperator parameter) {
        int i = parameter.applyAsInt(7315, 89163);
        System.out.println(i);
    }
}
import java.lang.Math;

class B {
    public static void main(String[] args) {
        A.method(Math::max);
    }
}
method1(Class1::method2);
method1((arg1, arg2) -> Class1.method2(arg1, arg2));
method1(new Interface1() {
    int method1(int arg1, int arg2) {
        return Class1.method2(arg1, agr2);
    }
});
(define (function scalar1 scalar2)
  (lambda (x) (* x scalar1 scalar2)))
@FunctionalInterface
interface CallbackHandler{
    public void onClick();
}

public class MyClass{
    public void doClick1(){System.out.println("doClick1");;}
    public void doClick2(){System.out.println("doClick2");}
    public CallbackHandler mClickListener = this::doClick;

    public static void main(String[] args) {
        MyClass myObjectInstance = new MyClass();
        CallbackHandler pointer = myObjectInstance::doClick1;
        Runnable pointer2 = myObjectInstance::doClick2;
        pointer.onClick();
        pointer2.run();
    }
}
Runnable              -> void run( );
Supplier<T>           -> T get( );
Consumer<T>           -> void accept(T);
Predicate<T>          -> boolean test(T);
UnaryOperator<T>      -> T apply(T);
BinaryOperator<T,U,R> -> R apply(T, U);
Function<T,R>         -> R apply(T);
BiFunction<T,U,R>     -> R apply(T, U);
//... and some more of it ...
Callable<V>           -> V call() throws Exception;
Readable              -> int read(CharBuffer) throws IOException;
AutoCloseable         -> void close() throws Exception;
Iterable<T>           -> Iterator<T> iterator();
Comparable<T>         -> int compareTo(T);
Comparator<T>         -> int compare(T,T);
Function<InputType, OutputType> functionname = (inputvariablename) {
... 
return outputinstance;
}
Collections.sort(list, new Comparator<CustomClass>(){
    public int compare(CustomClass a, CustomClass b)
    {
        // Logic to compare objects of class CustomClass which returns int as per contract.
    }
});
list.sort((a, b) ->  { a.isBiggerThan(b) } );
list.sort(MyClass::isBiggerThan);
void doCalculation(Function<Integer, String> calculation, int parameter) {
    final String result = calculation.apply(parameter);
}
doCalculation((i) -> i.toString(), 2);
Fun.With0Params<String> myFunctionField = "   hello world   "::trim;`  
Fun.With2Params<Boolean, Object, Object> equals = Objects::equals;`  
    
public void foo(Fun.With1ParamAndVoid<String> printer) throws Exception {
    printer.invoke("hello world);
}  

public void test(){
    foo(System.out::println);
}