【问题标题】:Java: self instantiating classesJava:自实例化类
【发布时间】:2021-05-14 00:49:52
【问题描述】:

我正在用 Java 为一个大学项目构建一个匹配工具,该项目基本上只包含几个更简单的匹配算法的集合。现在我希望人们能够轻松地添加自己的算法,并通过将 .java 文件添加到项目文件夹中来自动将它们包含到集成中。

每个算法都必须实现一个 MatchingComponentInterface,我希望实现这个接口的每个类都告诉集成它存在,以便集成可以动态组装自己,包括该算法。

对于一个简化的示例,让主代码和集成代码如下所示:

class Main {
  @Getter
  private Ensemble ensemble = new Ensemble();

  public static void main(String[] args){
    //SomeMatchingComponent.touch();
    Result res = ensemble.match(args[0], args[1]);
  }
}

注意注释的 touch() 调用,我稍后再讨论。

public class Ensemble{

  private List<MatchingComponentInterface> components;
  private Result combinedResult = new Result();

  public void addComponent(MatchingComponentInterface component){
    components.add(component);
  }

  public void match(Object first, Object second){
    components.forEach(component -> {
      combinedResult.addResult(component.match(first, second));
    });
  }
}

此外,我可能有几个 MatchingComponent 实现大致如下:

public class SomeMatchingComponent implements MatchingComponentInterface{

  //this is only executed the first time the class is mentioned in the code
  //however I want this do be executed without mentioning the class
  static {
    MatchingComponent foo = new MatchingComponent();
    Main.getEnsemble().addComponent(foo);
  }

  //static void touch(){}

  public Result match(Object first, Object second){
    //matching magic
  }
}

现在看一下静态代码块。只要我在代码中的其他地方使用该类,就会执行此代码。但是在这个例子中,这不会发生,因为我注释掉了 touch() 方法以及 main 方法中的调用。

当构建集成时,主要方法需要事先了解所有组件,以便触摸并将它们添加到集成中。但是我想添加它们而不添加任何内容。他们应该添加自己。

我现在的问题是:有没有办法强制执行静态代码块而无需硬编码存在哪些组件,或者让接口调用自身的所有实现?

【问题讨论】:

  • 也许别人有更好的答案,但是如果你所有的 MatchingComponentInterface 类都在同一个目录中,在启动时,你可以读取该目录中的 .java 文件并从文件中获取类名名字。
  • 谢谢吉尔伯特!我实际上有这个想法,但我想避免它并以编程方式进行。不过我找到了一种方法,如果您有兴趣,请查看我的答案。
  • @GilbertLeBlanc 标记你,因为我之前的评论中没有。

标签: java machine-learning matching


【解决方案1】:

我实际上已经找到了以编程方式解决该问题的解决方案。使用reflections 库,可以检测任何类的所有子类或任何接口的实现,因此使用这样的一些代码我可以实现我需要的:

public void addAllComponents(Ensemble ensemble){

  //"matching.component" is a prefix as all components are in a package with that name
  Reflections reflections = new Reflections("matching.component");
  Set<Class<? extends MatchingComponentInterface>> classes 
    = reflections.getSubTypesOf(MatchingComponentInterface.class);
  
  classes.forEach(aClass -> {
    try{
      ensemble.addComponent(aClass.getConstructor().newInstance());
    } 
    catch (NoSuchMethodException | IllegalAccessException | 
          InstantiationException | InvocationTargetException e) {
      //Handle exceptions appropriately
    }
  });
}

我在这里的一个非常老的问题中找到了这个库:

How can I get a list of all the implementations of an interface programmatically in Java?

【讨论】:

    猜你喜欢
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多