【问题标题】:Array of function pointers in Java [duplicate]Java中的函数指针数组[重复]
【发布时间】:2011-02-14 16:23:07
【问题描述】:

我已经阅读了this question,但我仍然不确定是否可以在 Java 的数组中保留指向方法的指针。如果有人知道这是否可能(或不可能),那将是一个真正的帮助。我正在尝试找到一个优雅的解决方案来保留Strings 和相关函数的列表,而无需编写成百上千的if 语句。

干杯

【问题讨论】:

    标签: java arrays pointers function


    【解决方案1】:

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

    【讨论】:

    • 干杯 cletus,这就是我要找的,这个例子有帮助;)
    • 有错误吗? " b.foo(); "
    【解决方案2】:

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

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

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

    class DoSomething extends Functor
    {
      public void execute()
      {
        System.out.println("blah blah blah");
      }
    }
    
    Functor [] myArray = new Functor[10];
    myArray[5] = new DoSomething();
    

    然后你可以调用:

    myArray[5].execute();
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • Method 并不是真正的函数指针。一方面,除非您调用静态方法,否则您需要将实例传递给它。
      • 是的,但您可以创建一个自动执行此操作的包装器。这将被称为 InstanceMethod 之类的东西,并实现与 Method 类似的方法,但委托调用并将传递给构造函数的对象传递给这些调用。也许Apache库有这样的东西?否则,编写自己的代码将是微不足道的。
      • 另外请记住,使用反射时必须小心,它会显着降低性能。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        我发现反射方法是最干净的——我在这个解决方案中添加了一个转折点,因为大多数生产类都有嵌套类,我没有看到任何示例可以证明这一点(但我也没有寻找很长时间)。我使用反射的原因是我下面的“updateUser()”方法有一堆冗余代码,并且中间只有一行更改(对于用户对象中的每个字段)更新了用户对象:

        NameDTO.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

        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

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 2021-12-27
            • 2018-08-24
            • 2018-08-27
            • 2013-03-01
            • 1970-01-01
            • 1970-01-01
            • 2020-08-21
            • 1970-01-01
            • 2014-01-04
            相关资源
            最近更新 更多