【问题标题】:Finding specific implementation of generic interface on classpath [duplicate]在类路径上查找通用接口的具体实现 [重复]
【发布时间】:2017-02-17 15:15:52
【问题描述】:

我最近(两次)遇到了以下问题 - 是否可以在类路径中找到通用接口的特定实现?为了可视化这一点,请考虑以下代码 sn-ps:

public interface Cleaner<T extends Room> {}
public class KitchenCleaner implements Cleaner<Kitchen> {}
public class BathroomCleaner implements Cleaner<Bathroom> {}

现在 - 是否有可能有以下方法?:

public static <T extends Room> findCleanerServiceForRoomType(T room) {
    return ???
}

返回 Kitchen 类的 KitchenCleaner 和 Bath 类的 BathroomCleaner?当然我希望它可以扩展,这样当添加新的房间和服务类型时,这个方法仍然有效......所以没有开关或 ifs :)

【问题讨论】:

  • 如果它们是你的类,你可以向接口添加一个 getType() 方法,你可以在你的 .jar 文件中包含一个 SPI 描述符并使用java.util.ServiceLoader
  • 主要问题是找到类路径上的所有类。 Java 没有对此的内置支持。但是你可以自己做,通过枚举类路径上的所有类;或找到一些这样做的图书馆。然后,对于每个类,您可以使用反射来查看它是否实现了某些特定的CleanerT
  • 通常情况下,所谓的重复不是同一个问题,并且会阻止发布有用的答案。我的建议:没有对此的自动支持,所以创建一个包含 Map&lt;Class,Class&gt; 的 CleanerRegistry(或者可能类似于 Map&lt;Class&lt;R extends Room&gt;, Class&lt;C extends Cleaner&gt;&gt;)。

标签: java generics classpath


【解决方案1】:

您可以向 Room 定义(接口或抽象类)添加一个方法,为您提供适当的清洁器。由于添加房间时需要添加 Cleaner,因此无需额外配置。

public interface Room {
  Cleaner<? extends Room> cleanerInstance();
}

public class Bathroom implements Room {
  public Cleaner<Bathroom> cleanerInstance(){
    return new BathroomCleaner();
  }
}

如果你想在房间不知道的情况下找到它,你需要某种配置或查找。

【讨论】:

  • 如此明显。谢谢:)我会接受这个答案,因为它解决了一种情况。这个解决方案无法解决另一个问题,尽管由于 Room 类不是我的类,它来自库(实际上是枚举)......但我可以在那里使用 switch 语句,因为它在工厂中。谢谢!
  • 不客气,祝你好运!
  • 这段代码的一个问题是 Cleaner 的类型与 Room 类型无关,除非是通过显式创建。仍然可以在 Room 上使用不合适的 Cleaner(因为 cleanerInstance() 是扩展 Room 的类型,而不是特定的类)您可以将 Room 声明为 Room&lt;T extends Room&gt; 这允许您执行 public class Bathroom implements Room&lt;Bathroom&gt;Cleaner&lt;T&gt; cleanerInstance(); 更多明确地将它们联系在一起。
【解决方案2】:

由于泛型在编译之外不存在,所以这个问题的答案是否定的

【讨论】:

  • 我知道通用参数被删除了,但这根本不能回答我的问题:) 下面实际上是一个很好的答案:)
【解决方案3】:

由于泛型在运行时擦除类型,我建议您在返回已清理房间的接口中放置一个泛型方法:

public Class<? extends Room> getCleanedClass(){
    //override in every implementation
    return Kitchen.class;
}

然后你可以在这个方法上使用谓词。

【讨论】:

  • 我不确定这如何解决问题。
  • 好吧,我假设您已经可以扫描整个 classPath 以获取每个类,您只需要克服类型擦除即可在类级别执行检查。但很高兴看到您找到了解决方案。
猜你喜欢
  • 2010-09-30
  • 2018-01-01
  • 2012-04-16
  • 2010-11-12
  • 2011-03-08
  • 2012-09-14
  • 1970-01-01
  • 2010-12-17
  • 2016-10-26
相关资源
最近更新 更多