Java中的函数指针数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2752192/
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-13 12:27:58  来源:igfitidea点击:

Array of function pointers in Java

javaarrayspointersfunction

提问by Waltzy

I have read this questionand I'm still not sure whether it is possible to keep pointers to methods in an array in Java, if anyone knows if this is possible or not it would be a real help. I'm trying to find an elegant solution of keeping a list of Strings and associated functions without writing a mess of hundreds of 'if's.

我已经阅读了这个问题,但我仍然不确定是否可以在 Java 中将指向方法的指针保留在数组中,如果有人知道这是否可行,那将是一个真正的帮助。我试图找到一种优雅的解决方案,可以保留字符串和相关函数的列表,而无需编写成百上千的“if”。

Cheers

干杯

采纳答案by cletus

Java doesn't have a function pointer per se (or "delegate" in C# parlance). This sort of thing tends to be done with anonymous subclasses.

Java 本身没有函数指针(或 C# 中的“委托”)。这种事情往往是用匿名子类来完成的。

public interface Worker {
  void work();
}

class A {
  void foo() { System.out.println("A"); }
}

class B {
  void bar() { System.out.println("B"); }
}

A a = new A();
B b = new B();

Worker[] workers = new Worker[] {
  new Worker() { public void work() { a.foo(); } },
  new Worker() { public void work() { b.bar(); } }
};

for (Worker worker : workers) {
  worker.work();
}

回答by Chris Dennett

It is possible, you can use an array of Method. Grab them using the Reflection API (edit: they're not functions since they're not standalone and have to be associated with a class instance, but they'd do the job -- just don't expect something like closures)

有可能,您可以使用Method数组。使用 Reflection API 获取它们(编辑:它们不是函数,因为它们不是独立的并且必须与类实例相关联,但它们会完成这项工作——只是不要指望像闭包这样的东西)

回答by Alex Martelli

Java does not have pointers (only references), nor does it have functions (only methods), so it's doubly impossible for it to have pointers to functions. What you cando is define an interface with a single method in it, have your classes that offer such a method declare they implement said interface, and make a vector with references to such an interface, to be populated with references to the specific objects on which you want to call that method. The only constraint, of course, is that all the methods must have the same signature (number and type of arguments and returned values).

Java 没有指针(只有引用),也没有函数(只有方法),所以它不可能有函数指针。您可以做的是定义一个包含单个方法的接口,让提供此类方法的类声明它们实现所述接口,并制作一个包含对此类接口的引用的向量,以填充对特定对象的引用你想调用那个方法。当然,唯一的限制是所有方法必须具有相同的签名(参数和返回值的数量和类型)。

Otherwise, you can use reflection/introspection (e.g. the Methodclass), but that's not normally the simplest, most natural approach.

否则,您可以使用反射/内省(例如Method类),但这通常不是最简单、最自然的方法。

回答by Fabio Ceconello

You can achieve the same result with the functor pattern. For instance, having an abstract class:

您可以使用函子模式获得相同的结果。例如,有一个抽象类:

abstract class Functor
{
  public abstract void execute();
}

Your "functions" would be in fact the execute method in the derived classes. Then you create an array of functors and populate it with the apropriated derived classes:

您的“函数”实际上是派生类中的 execute 方法。然后创建一个函子数组并用适当的派生类填充它:

class DoSomething extends Functor
{
  public void execute()
  {
    System.out.println("blah blah blah");
  }
}

Functor [] myArray = new Functor[10];
myArray[5] = new DoSomething();

And then you can invoke:

然后你可以调用:

myArray[5].execute();

回答by Robert

You are right that there are no pointers in java because a reference variables are the same as the & syntax in C/C++ holding the reference to the object but no * because the JVM can reallocate the heap when necessary causing the pointer to be lost from the address which would cause a crash. But a method is just a function inside a class object and no more than that so you are wrong saying there are no functions, because a method is just a function encapsulated inside an object. As far as function pointers, the java team endorses the use of interfaces and nested classes which all fine and dandy, but being a C++/C# programmer who uses java from time to time, I use my Delegate class I made for java because I find it more convenient when I need to pass a function only having to declare the return type of the method delegate. It all depends on the programmer. I read the white pages on why delegates are not support but I disagree and prefer to think outside the box on that topic.

您是对的,java 中没有指针,因为引用变量与 C/C++ 中保存对象引用的 & 语法相同,但没有 * 因为 JVM 可以在必要时重新分配堆,从而导致指针丢失会导致崩溃的地址。但是方法只是类对象内的一个函数,仅此而已,所以说没有函数是错误的,因为方法只是封装在对象内的函数。至于函数指针,java 团队支持使用接口和嵌套类,这些都很好,但作为一个不时使用 java 的 C++/C# 程序员,我使用我为 java 制作的 Delegate 类,因为我发现当我需要传递一个函数时更方便,只需声明方法委托的返回类型。这一切都取决于程序员。我阅读了有关为什么不支持代表的白页,但我不同意并且更愿意在该主题上跳出框框思考。

回答by user1266599

I found the reflection approach the cleanest -- I added a twist to this solution since most production classes have nested classes and I didn't see any examples that demonstrates this (but I didn't look for very long either). My reason for using reflection is that my "updateUser()" method below had a bunch of redundant code and just one line that changed (for every field in the user object) in the middle that updated the user object:

我发现反射方法是最干净的——我在这个解决方案中添加了一个变化,因为大多数生产类都有嵌套类,而且我没有看到任何演示这一点的示例(但我也没有寻找很长时间)。我使用反射的原因是我updateUser()下面的“

NameDTO.java

名称DTO.java

public class NameDTO {

    String first, last;

    public String getFirst() {
        return first;
    }

    public void setFirst(String first) {
        this.first = first;
    }

    public String getLast() {
        return last;
    }

    public void setLast(String last) {
        this.last = last;
    }   
}

UserDTO.java

用户DTO.java

public class UserDTO {

    private NameDTO name;
    private Boolean honest;

    public UserDTO() {
        name = new NameDTO();
        honest = new Boolean(false);
    }

    public NameDTO getName() {
        return name;
    }

    public void setName(NameDTO name) {
        this.name = name;
    }

    public Boolean getHonest() {
        return honest;
    }

    public void setHonest(Boolean honest) {
        this.honest = honest;
    }
}

Example.java

例子.java

import java.lang.reflect.Method;

public class Example {

    public Example ()  {
        UserDTO dto = new UserDTO();

        try {
            Method m1 = dto.getClass().getMethod("getName", null);
            NameDTO nameDTO = (NameDTO) m1.invoke(dto, null);

            Method m2 = nameDTO.getClass().getMethod("setFirst", String.class);
            updateUser(m2, nameDTO, "Abe");

            m2 = nameDTO.getClass().getMethod("setLast", String.class);
            updateUser(m2, nameDTO, "Lincoln");

            m1 = dto.getClass().getMethod("setHonest", Boolean.class);
            updateUser(m1, dto, Boolean.TRUE);
            System.out.println (dto.getName().getFirst() + " " + dto.getName().getLast() + ": honest=" + dto.getHonest().toString());

        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

    public  void updateUser(Method m,  Object o, Object v) {
        //  lots of code here
        try {
            m.invoke(o, v);
        } catch (Exception e) {
            e.printStackTrace();
        } 
        // lots of code here -- including a retry loop to make sure the
        // record hadn't been written since my last read
    }

    public static void main(String[] args) {
        Example mp = new Example();
    }
}