2017-06-02 10 views
0

私にはclasstypeのリストがあります。私は、明確な価値を処理することができる特定のクラスを見つけたいと思っています。メソッドの実装でクラスを動的に見つける方法は?

次の例では、各実装で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)'メソッドで定義されています。しかし、私はclasstypeのメソッドを呼び出すことはできませんので、私はこのように見つけることはできません。 – membersound

+0

新しいinstaceを作成し、それを 'c.newInstance()。supports(" TEST ");' – Jens

答えて

1

たとえば、実装に注釈を付けることができるという注釈@Supportsを作成できます。

この注釈は、次のようになります。

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

    String value(); 
} 

Class.isAnnotationPresentを使用することにより、実装がneedeアノテーションを持っている天気をかを確認することができますし、注釈を取得し、サポートを受けるためにvalue()メソッドにアクセスすることができClass.getAnnotationを使用して値。

+0

私は 'supports()'が 'return value.equals(SOME_CONSTANT)'以上のことをしたと推測しました。私は間違っていると思う。 – slim

2

リストあなたがMyServiceでのAPI与え、実行することはできませんのために求めている何

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

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

残念ながら、私は実行ごとにサービスの新しいインスタンスが必要です。だから私はリストにサービスインスタンスを置くことはできません。私はそれらを再利用することはできません。 – membersound

+0

ok私にチェックさせてください! –

1

内のすべての要素のメソッドを呼び出す必要があるので、あなたが代わりにList<MyInterface>を行う必要があります。

特定のクラスが文字列値をサポートするかどうかを調べる方法は、非静的メソッドsupports()を呼び出すことです。したがって、インスタンスを作成して呼び出す必要があります。

Javaでは、インターフェイスで静的メソッドを定義することはできません。

私の忠告は、これと戦うことではなく、あなたのデザインに何か問題があることを示すものです。あなたはClass<?>のリストを持っているではなくでなく、MyInterfaceのリストを持っているほうがよいでしょう。ステートレスでリエントラントにすると、supports()process()に簡単に電話することができます。

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

これは、特にSpringのようなフレームワークでは非常に一般的なパターンです。初期化時にMyInterfaceオブジェクトのリストを作成し、プログラムの存続期間中に再利用します。

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

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

...

あなたはたびに新しいインスタンスを作成する必要がある場合は、代わりに、タイプのリストの、それぞれに対応するファクトリオブジェクトを作成するには、MyInterfaceFactoryのリストを持っています

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

(このように多くの書き込みが繰り返されるようであれば、より動的に行うことができますが、やり方をやり直すことから始めます)。あなたは、実行時に調べることができ、クラスのリストを持っていると判断している場合


  • あなたがインターフェイスで宣言されていない静的supports()方法を標準化できます。あなたはReflectionを通じてこれを呼び出さなければならず、Javaの型安全性を持たないでください。
  • カスタム注釈

で何かを行うことができるかもしれない。しかし、あなたがどんな自由を持っている場合は、これらのいずれかを実行しないでください。

+0

これで私はそのインターフェイスを定義するすべてのクラスを取得しています。しかし、私は実際にインターフェイスメソッド 'supports()'を実行していません。しかし、このメソッドは実装をまったく使用できるかどうかを定義するため、これは重要です。 – membersound

+0

upvoterに謝罪して、私はこれを完全に書き直しました。 – slim

関連する問題