2010-05-02 57 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(); 
    } 
}