2017-02-20 31 views
0

我有一個兩個簡單的類,並使用反射模式調用方法。 我想寫模塊編程。 假設我們有一個數據庫表中保持模塊名稱:如何使用消費者和供應商,而不是反思java 8

Id moduleName methodName ClassName    active 
1  sample  a   com.examle.sample  true 
2  SMS  sendSMS  com.example.SMS   false 
3  Email  sendEmail com.example.Email  false 
... ...   ...      ... 

激活時是真模塊必須activated.So當我寫一個程序,並編譯,我不喜歡再編譯整個MyApp的。所以我使用反射模式來調用模塊。請參閱代碼。

public class Sample { 
    public void a() { 
     System.out.println("Call Method a"); 
    } 
} 
public class SMS { 
    public void sendSMS(String str) { 
     System.out.println("send SMS ok"); 
    } 
} 
public class Email { 
    public void sendEmail(String str) { 
     System.out.println("send Email ok"); 
    } 
} 
public class SampleMainClass { 
    public static void main(String[] args) { 

      //coonect to database and fetch all record in tables 
     while(record.next){ 
      if (record.getActive()){   
      Object o = Class.forName(record.getClssName()).newInstance() ; 
      Method method = o.getClass().getDeclaredMethod(record.getMethodName()); 
      method.invoke(o); 
      }        
     } 
    } 

輸出

Call Method a 

所以我在Java 8聽見,反射圖案是棄用,取而代之的是,我們可以利用消費者和供應商。

如何使用消費者和供應商代替反思在java 8?

謝謝。

+0

你的例子不是一個很好的用例,因爲它首先使用反射是沒有意義的。嘗試提供一個示例來展示反射的* need *,而不是* how *它的使用。 – shmosel

回答

4
public class Q42339586 { 

    static class Sample { 
     void a() { System.out.println("a() called"); } 
     void b() { System.out.println("b() called"); } 
    } 

    static <T> void createInstanceAndCallMethod(
      Supplier<T> instanceSupplier, Consumer<T> methodCaller) { 
     T o = instanceSupplier.get(); 
     methodCaller.accept(o); 
    } 

    public static void main(String[] args) { 
     createInstanceAndCallMethodJava8(Sample::new, Sample::a); 
    } 

} 

這裏,createInstanceAndCallMethod做什麼是你的main()方法做,但它接受的參數來代替。

A Supplier用於創建新實例,並且Consumer用於調用該實例上的特定方法。在這個例子中,兩個方法引用都作爲兩個參數傳遞。相反,您也可以使用lambda表達式,然後編寫() -> new Sample()o -> o.a()。請參閱this official tutorial part瞭解更多信息。

在反射的優點是顯而易見的:

  1. 你不能要求createInstanceAndCallMethod創建一個不存在的類的實例。
  2. 您不能要求createInstanceAndCallMethod調用某個特定類中不存在的方法。
  3. 由於你不必處理任何檢查的異常。

當然,只有在代碼中的某個地方,實際的類和方法是已知的,例如,從屬性文件中讀取類和方法名稱是不可能的,然後使用Java 8機制安全地創建實例並調用特定的方法。

+0

也可能有性能優勢。 – shmosel

+0

不是downvoting或任何東西,但「例如不能從屬性文件中讀取類和方法名稱,然後使用Java 8機制安全地創建實例並調用特定的方法。」這不正是問題所針對的(編輯後的版本)嗎?這怎麼可能是被接受的答案?這並不回答如何動態調用給定類的給定方法,而只是預先知道的方法和類。 – GPI

+0

謝謝。 「從屬性文件中讀取類和方法名稱是不可能的」,所以如何在java 8中進行模塊編程? – user6920966

2

ConsumerSupplier是功能接口,它們不引用反射。

這是不同的事情。

所以我聽到在java 8中,反射模式是不贊成,而是我們可以使用消費者和供應商。

錯誤的信息。

+0

功能接口和lambda允許簡潔的動態方法調用,這是不可能的,直到Java 8不使用反射。我認爲這就是OP所取得的成就,儘管提供的例子很難證明。 – shmosel

+0

「功能接口允許方法簡潔地引用」好吧,這可能是因爲方法引用和lambda表達式。但是我的回答有什麼問題?我們可以創建相同的'Supplier'和'Consumer'接口並在Java 7中使用它們。請解釋。 – Vusal

+0

關鍵是*簡潔*。沒有任何反映,沒有Java 7中'Class :: method'的等價物。 – shmosel

相關問題