Java 中的函数指针

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1073358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:08:42  来源:igfitidea点击:

Function Pointers in Java

javapointersdelegatesfunction-pointers

提问by dreadwail

This may be something common and trivial, but I seem to be having trouble finding a concrete answer. In C# there is a concept of delegates, which relates strongly to the idea of function pointers from C++. Is there a similar functionality in Java? Given that pointers are somewhat absent, what is the best way about this? And to be clear, we're talking first class here.

这可能是一些常见而微不足道的事情,但我似乎很难找到具体的答案。在 C# 中有一个委托的概念,它与 C++ 中的函数指针的思想密切相关。Java 中是否有类似的功能?鉴于指针有些缺失,最好的方法是什么?需要明确的是,我们在这里谈论的是头等舱。

采纳答案by Michael Borgwardt

The Java idiom for function-pointer-like functionality is an an anonymous class implementing an interface, e.g.

类似函数指针的功能的 Java 习惯用法是一个实现接口的匿名类,例如

Collections.sort(list, new Comparator<MyClass>(){
    public int compare(MyClass a, MyClass b)
    {
        // compare objects
    }
});

Update:the above is necessary in Java versions prior to Java 8. Now we have much nicer alternatives, namely lambdas:

更新:在 Java 8 之前的 Java 版本中,上述内容是必需的。现在我们有更好的替代方案,即 lambdas:

list.sort((a, b) -> a.isGreaterThan(b));

and method references:

和方法参考:

list.sort(MyClass::isGreaterThan);

回答by jwoolard

No, functions are not first class objects in java. You can do the same thing by implementing a handler class - this is how callbacks are implemented in the Swing etc.

不,函数不是java中的第一类对象。您可以通过实现处理程序类来做同样的事情 - 这就是在 Swing 等中实现回调的方式。

There are however proposals for closures (the official name for what you're talking about) in future versions of java - Javaworldhas an interesting article.

然而,在 Java 的未来版本中,有关于闭包的建议(您所谈论的正式名称)—— Javaworld有一篇有趣的文章。

回答by raupach

You can substitue a function pointer with an interface. Lets say you want to run through a collection and do something with each element.

您可以用接口替换函数指针。假设你想遍历一个集合并对每个元素做一些事情。

public interface IFunction {
  public void execute(Object o);
}

This is the interface we could pass to some say CollectionUtils2.doFunc(Collection c, IFunction f).

这是我们可以传递给某些人的接口,比如 CollectionUtils2.doFunc(Collection c, IFunction f)。

public static void doFunc(Collection c, IFunction f) {
   for (Object o : c) {
      f.execute(o);
   }
}

As an example say we have a collection of numbers and you would like to add 1 to every element.

举个例子,假设我们有一个数字集合,你想给每个元素加 1。

CollectionUtils2.doFunc(List numbers, new IFunction() {
    public void execute(Object o) {
       Integer anInt = (Integer) o;
       anInt++;
    }
});

回答by VoidPointer

There is no such thing in Java. You will need to wrap your function into some object and pass the reference to that object in order to pass the reference to the method on that object.

Java 中没有这样的东西。您需要将函数包装到某个对象中并传递对该对象的引用,以便将该引用传递给该对象上的方法。

Syntactically, this can be eased to a certain extent by using anonymous classes defined in-place or anonymous classes defined as member variables of the class.

从语法上讲,这可以通过使用就地定义的匿名类或定义为类成员变量的匿名类在一定程度上得到缓解。

Example:

例子:

class MyComponent extends JPanel {
    private JButton button;
    public MyComponent() {
        button = new JButton("click me");
        button.addActionListener(buttonAction);
        add(button);
    }

    private ActionListener buttonAction = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // handle the event...
            // note how the handler instance can access 
            // members of the surrounding class
            button.setText("you clicked me");
        }
    }
}

回答by Kingamajick

To achieve similar functionality you could use anonymous inner classes.

要实现类似的功能,您可以使用匿名内部类。

If you were to define a interface Foo:

如果你要定义一个接口Foo

interface Foo {
    Object myFunc(Object arg);
}

Create a method barwhich will receive a 'function pointer' as an argument:

创建一个bar接收“函数指针”作为参数的方法:

public void bar(Foo foo) {
    // .....
    Object object = foo.myFunc(argValue);
    // .....
}

Finally call the method as follows:

最后调用方法如下:

bar(new Foo() {
    public Object myFunc(Object arg) {
        // Function code.
    }
}

回答by Yuval F

This brings to mind Steve Yegge's Execution in the Kingdom of Nouns. It basically states that Java needs an object for every action, and therefore does not have "verb-only" entities like function pointers.

这让人想起史蒂夫·耶格在名词王国处决。它基本上表明 Java 的每个动作都需要一个对象,因此没有像函数指针这样的“仅动词”实体。

回答by Mario Fusco

Check the closures how they have been implemented in the lambdaj library. They actually have a behavior very similar to C# delegates:

检查闭包是如何在 lambdaj 库中实现的。它们实际上具有与 C# 委托非常相似的行为:

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

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

回答by Lawrence Dol

I have implemented callback/delegate support in Java using reflection. Details and working source are available on my website.

我已经使用反射在 Java 中实现了回调/委托支持。详细信息和工作来源可在我的网站上找到

How It Works

这个怎么运作

We have a principle class named Callback with a nested class named WithParms. The API which needs the callback will take a Callback object as a parameter and, if neccessary, create a Callback.WithParms as a method variable. Since a great many of the applications of this object will be recursive, this works very cleanly.

我们有一个名为 Callback 的原理类和一个名为 WithParms 的嵌套类。需要回调的 API 将接受一个 Callback 对象作为参数,并在必要时创建一个 Callback.WithParms 作为方法变量。由于这个对象的很多应用程序都是递归的,所以这非常干净。

With performance still a high priority to me, I didn't want to be required to create a throwaway object array to hold the parameters for every invocation - after all in a large data structure there could be thousands of elements, and in a message processing scenario we could end up processing thousands of data structures a second.

由于性能仍然是我的重中之重,我不想被要求创建一个一次性对象数组来保存每次调用的参数 - 毕竟在大型数据结构中可能有数千个元素,并且在消息处理中我们可能最终每秒处理数千个数据结构。

In order to be threadsafe the parameter array needs to exist uniquely for each invocation of the API method, and for efficiency the same one should be used for every invocation of the callback; I needed a second object which would be cheap to create in order to bind the callback with a parameter array for invocation. But, in some scenarios, the invoker would already have a the parameter array for other reasons. For these two reasons, the parameter array did not belong in the Callback object. Also the choice of invocation (passing the parameters as an array or as individual objects) belongs in the hands of the API using the callback enabling it to use whichever invocation is best suited to it's inner workings.

为了线程安全,API 方法的每次调用都需要唯一存在的参数数组,并且为了提高效率,每次调用回调都应该使用相同的参数数组;我需要创建第二个对象,以便将回调与参数数组绑定以进行调用。但是,在某些情况下,由于其他原因,调用者已经拥有一个参数数组。由于这两个原因,参数数组不属于回调对象。此外,调用的选择(将参数作为数组或作为单个对象传递)属于使用回调的 API 的手中,使其能够使用最适合其内部工作的调用。

The WithParms nested class, then, is optional and serves two purposes, it contains the parameter object array needed for the callback invocations, and it provides 10 overloaded invoke() methods (with from 1 to 10 parameters) which load the parameter array and then invoke the callback target.

WithParms 嵌套类是可选的,有两个用途,它包含回调调用所需的参数对象数组,它提供 10 个重载的 invoke() 方法(具有 1 到 10 个参数),这些方法加载参数数组,然后调用回调目标。

回答by zoquete

You can use reflection to do it.

您可以使用反射来做到这一点。

Pass as parameter the object and the method name (as a string) and then invoke the method. For example:

将对象和方法名称(作为字符串)作为参数传递,然后调用该方法。例如:

Object methodCaller(Object theObject, String methodName) {
   return theObject.getClass().getMethod(methodName).invoke(theObject);
   // Catch the exceptions
}

And then use it as in:

然后像这样使用它:

String theDescription = methodCaller(object1, "toString");
Class theClass = methodCaller(object2, "getClass");

Of course, check all exceptions and add the needed casts.

当然,检查所有异常并添加所需的强制转换。

回答by ozgeneral

Relative to most people here I am new to java but since I haven't seen a similar suggestion I have another alternative to suggest. Im not sure if its a good practice or not, or even suggested before and I just didn't get it. I just like it since I think its self descriptive.

相对于这里的大多数人,我是 Java 新手,但由于我没有看到类似的建议,我有另一种建议。我不确定它是否是一个好的做法,或者甚至之前建议过,我只是没有得到它。我只是喜欢它,因为我认为它具有自我描述性。

 /*Just to merge functions in a common name*/
 public class CustomFunction{ 
 public CustomFunction(){}
 }

 /*Actual functions*/
 public class Function1 extends CustomFunction{
 public Function1(){}
 public void execute(){...something here...}
 }

 public class Function2 extends CustomFunction{
 public Function2(){}
 public void execute(){...something here...}
 }

 .....
 /*in Main class*/
 CustomFunction functionpointer = null;

then depending on the application, assign

然后根据应用程序,分配

 functionpointer = new Function1();
 functionpointer = new Function2();

etc.

等等。

and call by

并打电话

 functionpointer.execute();