Java 将 Class<> 限制为特定类型

Java restricting Class<> to specific types

我对 Java 泛型和 Class<> clazz 类型很陌生,我有一个接口

public interface MyInterface {
void doSomething(String arg1);
}

由多个classes

实现
class MyInterfaceImplFirst implements MyInterface {
  private arg;
  public MyInterfaceImplFirst(String arg) {
    this.arg = arg;
  }

  @Override
  void doSomething(String arg1) {
    //...
  }
}

class MyInterfaceImplSecond implements MyInterface {
  private arg;
  public MyInterfaceImplSecond(String arg) {
    this.arg = arg;
  }

  @Override
  void doSomething(String arg1) {
    //...
  }
}

我有一个 class 接受 Class<MyInterface> type

public class Dummy {
  public void load(Class<MyInterface> clazz) {
    //...
  }

  public static void main(String[] args) {
    Dummy dummy = new Dummy();
    //The below does not compile
    dummy.load(MyInterfaceImplFirst.class);
  }
}

如果我将加载方法更改为 public void load(Class clazz) 它工作正常,谁能告诉我如何将参数限制为加载方法仅属于 MyInterface ?

的子类型(impl)

PECS (Producer-Extends, Consumer-Super) 是问题所在。给定一个 List<Number>,你当然可以调用 .add(someDouble)。因此,当需要 List<Number> 时,不能传递 List<Integer> 。 'write' 概念不适用于 Class<X>,但 java 不适用于 'know',因此当Class<TheInterface> 为必填项。

PECS 有点用词不当;它是从泛型类型的角度编写的(因此,List、Class 等)。如果 class 只产生东西而不会消耗任何泛型类型,这里就是这种情况,PECS 声明你应该使用 extends.

因此,public void load<Class<? extends MyInterface> clazz)就是你想要的。

一些注意事项:

  • 泛型服务于 link 事物。如果你声明一个通用变量并在 0 或 1 个地方使用它,那么你就是在搞乱 黑客 java 的类型系统(在合法的情况下一个好主意,但很少见)。鉴于你在任何地方都不需要那个 T,你会搞砸的。只需使用 ? 即可。
  • 混合泛型和 Class 通常是不好的。有些东西 Class 可以表示,例如 intClass<?> c = int.class; 有效 java),泛型不能(List<int> 无效 [=55] =]),反之亦然,泛型可以表示 class 不能。您不能拥有代表 List<String>java.lang.Class 实例(仅 List - 原始类型)。 Class<List<String>> 不是东西; List<String>.class 不起作用。 List<List<String>> 确实有效。
  • 无论你怎么想:我知道!我将制作一个接口,使用泛型,然后制作一个 Class<? extends MyInterface> - 这可能是一个错误。你没有解释是什么让你认为你需要这个。最有可能的是,正确的答案是工厂。工厂本质上是对构造函数的抽象。