2017-06-02 59 views
0

我有一個類型列表。我想找到一個有資格處理不同價值的特定類。如何通過其方法實現動態地找到類?

在以下示例中,每個實現必須提供supports(String)方法。並定義這個類支持哪些值。

問題:我沒有對象在列表中,但分類型。因此我不能在其上調用自定義方法,如supports()

List<Class<MyService>> list; 

public Object getInstanceThatSupports(String val) { 
    val = "TEST"; 

    for (Class<MyService> c : list) { 
     if (c.supports(val)) { //TODO this is invalid 
      return c.newInstance().process(val); 
     } 
    } 
} 

public interface MyService { 
    boolean supports(String val); 
    void process(String val); 
} 

public class MyServiceImpl implements MyService { 
    @Override 
    public boolean supports(String val) { 
     return val.equals("TEST"); 
    } 

    @Override 
    public void process(String val) { 
     //handle the value 
    } 
} 

我該怎麼做到這一點?

+0

使用反射可以的方式,但它不是很清楚你想要什麼 – Jens

+0

那麼。如果我的輸入值是'TEST',我想找到支持該值的'MyService'實現。它由'supports(val)'方法定義。但是我不能在類型上調用這個方法,所以我找不到這種方法。 – membersound

+0

您可以創建一個新實例並將其稱爲'c.newInstance()。supports(「TEST」);' – Jens

回答

1

例如,您可以創建一個註釋@Supports,例如您可以使用註釋來實現註釋。

這個註釋可能看起來像這樣:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface Supports { 

    String value(); 
} 

通過使用Class.isAnnotationPresent你可以請檢查是否或不實施具有neede註釋和使用Class.getAnnotation你得到的註解,並且可以訪問value()方法來獲得支持值。

+0

我曾經猜測'supports()'做的不止是'return value.equals(SOME_CONSTANT)'。我想我猜錯了。 – slim

2

,因爲你需要調用的所有元素的方法列表

List<MyInterface> list = Arrays.asList(new MyImpl(), new MyImpl2()); 
String val = "TEST"; 

for (MyInterface x : list) { 
    if (x.supports(val)) { 
     //TODO 
    } 
} 
+0

不幸的是,我需要在每次執行時都提供一個新的服務實例。所以我不能把服務實例放入列表中。我無法重用它們。 – membersound

+0

好吧,讓我檢查! –

1

你問什麼不能做,因爲你的MyService的API,你應該做的,而不是List<MyInterface>

只有找出給定類是否支持字符串值的方法是調用supports()這是一種非靜態方法。所以你必須創建一個實例才能調用它。

Java不允許您在接口中定義靜態方法。

我的建議是不要打這個,並將其作爲您的設計出現問題的指示。你會更好而不是有一個列表Class<?>,而是有一個列表MyInterface。使它們成爲無狀態和可重入的,然後您可以輕鬆地撥打supports()process()

for(MyInterface obj : objs) { 
    if(obj.supports(s)) { 
     obj.process(s); 
    } 
} 

這是一個非常常見的模式,特別是像Spring這樣的框架。您將在初始時創建MyInterface對象的列表,並在程序的整個生命週期中重新使用它。

如果必須每次創建新實例,創建爲每一個相應的工廠對象,而不是一個類型列表,有MyInterfaceFactory列表:

public class MyInterfaceImplFactory implements MyInterfaceFactory { 
    public boolean supports(String s) { 
     // hard code this here 
    } 

    public MyInterfaceImpl newInstance() { 
     return new MyInterfaceImpl(); 
    } 
} 

...

for(MyInterfaceFactory factory : factories) { 
    if(factory.supports(s)) { 
     MyInterface obj = factory.newInstance(); 
     obj.process(s); 
    } 
} 

(如果你有這麼多寫這些的人會變得重複性的,你可以更動態地做到 - 但以愚蠢的方式開始)。


如果你確定有類的列表,你可以在運行時檢查:

  • ,你可以對其他沒有在接口中聲明靜態supports()方法標準化。你必須通過Reflection來調用它,並且不需要Java的類型安全性。
  • 你也許能夠做一些定製的註解

但不要做任何的這些,如果您有任何自由。

+0

好吧,我得到所有類定義該接口。但我實際上並沒有執行接口方法'supports()'。但這是至關重要的,因爲此方法定義了是否可以使用該實現。 – membersound

+0

我對這個問題表示歉意,我已經完全重寫了這個。 – slim