如何通过方法实现动态查找类?

时间:2017-06-02 10:00:31

标签: java arraylist interface

我有一个classtypes列表。我想找到一个有资格处理不同值的特定类。

在以下示例中,每个实现都必须提供supports(String)方法。并定义此类支持的值。

问题:我在列表中没有对象,但 classtypes 。因此,我无法在其上调用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
   }
}

我怎么能做到这一点?

3 个答案:

答案 0 :(得分:2)

你应该改为List<MyInterface> list = Arrays.asList(new MyImpl(), new MyImpl2()); String val = "TEST"; for (MyInterface x : list) { if (x.supports(val)) { //TODO } } ,因为你需要调用列表中所有元素的方法

redirects().follow(false)

答案 1 :(得分:1)

根据MyService的API,您要求的内容无法完成。

方法来确定给定的类是否支持字符串值,是调用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的类型安全性。
  • 您可以使用自定义注释执行某些操作

但如果你有任何自由,不要做其中任何一项。

答案 2 :(得分:1)

您可以创建一个注释@Supports,例如您可以使用注释实现。

此注释可能如下所示:

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

    String value();
}

使用Class.isAnnotationPresent您可以检查实现是否具有neede注释,并使用Class.getAnnotation获取注释并可以访问value()方法以获取支持的值。< / p>