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

Java 如何通过类的方法实现动态查找类?,java,arraylist,interface,Java,Arraylist,Interface,我有一个类类型列表。我想找到一个适合处理不同值的特定类 在下面的示例中,每个实现都必须提供一个supports(String)方法。并定义该类支持哪些值 问题:列表中没有对象,只有类类型。因此,我无法对它们调用像supports()这样的自定义方法 List<Class<MyService>> list; public Object getInstanceThatSupports(String val) { val = "TEST"; for (Class

我有一个类类型列表。我想找到一个适合处理不同值的特定类

在下面的示例中,每个实现都必须提供一个
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
   }
}
列表;
公共对象getInstanceThatSupports(字符串val){
val=“测试”;
用于(c类:列表){
如果(c.supports(val)){//TODO,则此操作无效
返回c.newInstance().process(val);
}
}
}
公共接口MyService{
布尔支持(字符串val);
作废处理(字符串val);
}
公共类MyServiceImpl实现了MyService{
@凌驾
公共布尔支持(字符串val){
返回值等于(“测试”);
}
@凌驾
公共作废处理(字符串val){
//处理值
}
}

我怎样才能做到这一点呢?

您应该改为
List
,因为您需要调用列表中所有元素的方法

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

for (MyInterface x : list) {
    if (x.supports(val)) {
        //TODO
    }
}
List List=Arrays.asList(new MyImpl(),new MyImpl2());
字符串val=“测试”;
对于(MyInterface x:list){
如果(x.支持(val)){
//待办事项
}
}

您应该改为
List
,因为您需要调用列表中所有元素的方法

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

for (MyInterface x : list) {
    if (x.supports(val)) {
        //TODO
    }
}
List List=Arrays.asList(new MyImpl(),new MyImpl2());
字符串val=“测试”;
对于(MyInterface x:list){
如果(x.支持(val)){
//待办事项
}
}

考虑到MyService的API,您的请求无法实现

确定给定类是否支持字符串值的唯一方法是调用
supports()
,这是一个非静态方法。因此,您必须创建一个实例才能调用它

Java不允许在接口中定义静态方法

我的建议是不要反对这一点,并将其视为您的设计有问题的迹象。你最好不要有一个
的列表,而是有一个
MyInterface
的列表。将它们设置为无状态且可重入,然后您可以轻松调用
supports()
process()

这是一种非常常见的模式,尤其是在Spring这样的框架中。您应该在初始化时创建
MyInterface
对象列表,并在程序的生命周期中重用它

如果每次都必须创建一个新实例,请为每个实例创建一个相应的factory对象,并创建一个
MyInterfaceFactory
列表,而不是类型列表:

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

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

(如果你有这么多这样的东西,以至于写它们变得重复,你可以更动态地去做——但从愚蠢的方式开始)


如果确定要有一个类列表,可以在运行时检查:

  • 您可以对接口中未声明的静态
    supports()
    方法进行标准化。您必须通过反射来调用它,而不必使用Java的类型安全性
  • 您可能可以使用自定义注释执行某些操作

但是,如果你有任何自由,就不要做这两件事。

考虑到你MyService的API,你所要求的是做不到的

确定给定类是否支持字符串值的唯一方法是调用
supports()
,这是一个非静态方法。因此,您必须创建一个实例才能调用它

Java不允许在接口中定义静态方法

我的建议是不要反对这一点,并将其视为您的设计有问题的迹象。你最好不要有一个
的列表,而是有一个
MyInterface
的列表。将它们设置为无状态且可重入,然后您可以轻松调用
supports()
process()

这是一种非常常见的模式,尤其是在Spring这样的框架中。您应该在初始化时创建
MyInterface
对象列表,并在程序的生命周期中重用它

如果每次都必须创建一个新实例,请为每个实例创建一个相应的factory对象,并创建一个
MyInterfaceFactory
列表,而不是类型列表:

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

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

(如果你有这么多这样的东西,以至于写它们变得重复,你可以更动态地去做——但从愚蠢的方式开始)


如果确定要有一个类列表,可以在运行时检查:

  • 您可以对接口中未声明的静态
    supports()
    方法进行标准化。您必须通过反射来调用它,而不必使用Java的类型安全性
  • 您可能可以使用自定义注释执行某些操作

但是,如果您有任何自由,请不要执行这两项操作。

您可以创建一个注释
@支持
,例如,您可以使用该注释对实现进行注释

此注释可能如下所示:

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

    String value();
}

使用
Class.isAnnotationPresent
可以检查实现是否具有所需的注释,使用
Class.getAnnotation
可以获得注释并访问
值()
方法获取支持的值。

您可以创建一个注释
@Supports
,例如,您可以使用该注释对实现进行注释

此注释可能如下所示:

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

    String value();
}

通过使用
Class.isAnnotationPresent
可以检查实现是否具有所需的注释,使用
Class.getAnnotation
可以获得注释,并可以访问
value()
方法来获得支持的值。

使用反射可以是一种方法,但不太清楚您想要什么。如果我的输入值是
TEST
,我想找到支持的
MyService
实现