2010-05-02 67 views
11

我已阅读this question,我仍然不确定是否有可能在Java中保留指向数组中方法的指针,如果有人知道这是否可行,这将是一个真正的帮助。我试图找到一个优雅的解决方案,保留一个字符串列表和相关的函数,而不用编写数百个'if'的混乱。Java中函数指针的阵列

干杯

回答

24

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

欢呼声cletus,这是我正在寻找,例如帮助;) – Waltzy 2010-05-02 02:00:17

+1

是否有错误? “b.foo();” – 2011-07-31 08:52:00

3

这是可能的,你可以使用的Method数组。使用Reflection API抓取它们(编辑:它们不是函数,因为它们不是独立的,必须与类实例关联,但他们会完成这项工作 - 只是不期望像关闭那样的东西)

+0

“方法”并不是一个真正的函数指针。首先,除非您调用静态方法,否则您需要将实例传递给它。 – cletus 2010-05-02 01:55:50

+0

的确如此,但是您可以创建一个自动执行此操作的包装器。这将被称为像InstanceMethod,并实现类似的方法,但委托调用,并传递给这些调用传递给构造函数的对象。也许Apache库有这样的东西?否则,编写自己的代码会很麻烦。 – 2010-05-02 02:00:10

+0

创建你自己是学习的唯一方式,我认为,另一个好的答案。 – Waltzy 2010-05-02 02:01:56

2

Java没有指针(只有引用),也没有函数(只有方法),所以它有指向函数的双重可能性。你所能做的就是在其中定义一个具有单一方法的接口,让你的类提供这样一种方法,声明它们实现所述接口,并且创建一个引用这样的接口的向量,并填充参考特定要在其上调用该方法的对象。当然,唯一的约束是所有的方法必须具有相同的签名(参数的数量和类型以及返回的值)。否则,你可以使用反射/自省(例如Method类),但这通常不是最简单,最自然的方法。

12

您可以使用函子模式实现相同的结果。例如,抽象类:

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

您的“函数”实际上是派生类中的执行方法。然后创建仿函数的数组,并与apropriated派生类填充它:

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(); 
+4

“告诉我我的意思,而不是我要求的”谢谢。 – Waltzy 2010-05-02 02:10:04

1

你是正确的,在Java中没有指针,因为一个参考变量是相同的,如C/C++的&语法保持参考对象,但没有*因为JVM可以重新分配堆在必要时使指针从这将导致崩溃的地址丢失。但是,一个方法就是一个类对象中的函数,没有比这更使你错了说没有作用,因为一个方法就是封装对象内的函数。 至于函数指针的Java团队赞同使用的界面和所有罚款和花花公子,但作为一个C++/C#程序员谁使用Java不时,我用我的Delegate类我对Java,因为我做了嵌套类当我需要传递一个只需声明方法委托的返回类型的函数时,发现它更方便。这一切都取决于程序员。 我读了为什么代表们不支持白页,但我不同意,宁愿认为关于这一主题外箱。

2

我发现反射接近干净 - 我添加了一个转折这个解决方案,因为大多数生产类嵌套类和我没有看到,说明了这一点任何的例子(但我没有看很长任) 。我使用反射的原因是我的下面的“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(); 
    } 
}