Java: 自实例化 类
Java: self instantiating classes
我正在 Java 中为一个大学项目构建一个匹配工具,该项目基本上只包含几个更简单的匹配算法的集合。现在我希望人们能够轻松地添加自己的算法,并通过将 .java 文件添加到项目文件夹中来自动将它们包含到集成中。
每个算法都必须实现一个 MatchingComponentInterface,我想实现每个 class 实现这个接口告诉集成它存在,以便集成可以动态地 assemble 本身包括该算法。
为了简化示例,让主要代码和整体代码如下所示:
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
}
}
现在看看静态代码块。只要我在代码中的其他地方使用 class ,就会执行此代码。但是在这个例子中,这不会发生,因为我注释掉了 touch()
方法以及 main 方法中的调用。
构建集成时,主要方法需要事先知道所有组件,以便接触并将它们添加到集成中。但是我想添加它们而没有任何这些。他们应该自己添加。
我现在的问题是:有没有办法强制执行静态代码块而无需硬编码哪些组件存在或者让接口调用自身的所有实现?
我实际上找到了一个以编程方式解决该问题的解决方案。使用 reflections 库可以检测任何 class 的所有子 class 或任何接口的实现,因此使用一些像这样的代码我可以实现我需要的:
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?
我正在 Java 中为一个大学项目构建一个匹配工具,该项目基本上只包含几个更简单的匹配算法的集合。现在我希望人们能够轻松地添加自己的算法,并通过将 .java 文件添加到项目文件夹中来自动将它们包含到集成中。
每个算法都必须实现一个 MatchingComponentInterface,我想实现每个 class 实现这个接口告诉集成它存在,以便集成可以动态地 assemble 本身包括该算法。
为了简化示例,让主要代码和整体代码如下所示:
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
}
}
现在看看静态代码块。只要我在代码中的其他地方使用 class ,就会执行此代码。但是在这个例子中,这不会发生,因为我注释掉了 touch()
方法以及 main 方法中的调用。
构建集成时,主要方法需要事先知道所有组件,以便接触并将它们添加到集成中。但是我想添加它们而没有任何这些。他们应该自己添加。
我现在的问题是:有没有办法强制执行静态代码块而无需硬编码哪些组件存在或者让接口调用自身的所有实现?
我实际上找到了一个以编程方式解决该问题的解决方案。使用 reflections 库可以检测任何 class 的所有子 class 或任何接口的实现,因此使用一些像这样的代码我可以实现我需要的:
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?