Java 限制 Class<>到特定类型

发布于 2025-01-14 09:43:00 字数 1066 浏览 1 评论 0 原文

我对 Java 泛型和 Class>> 非常陌生。 接口

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

clazz 类型,我有一个由多个类实现的

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; 的类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) 它工作正常,有人可以告诉我如何将加载方法的参数限制为仅是子类型(impl) 我的界面

I am very new to Java generics and Class<> clazz type, I have an interface

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

which is implemented by multiple 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) {
    //...
  }
}

I have a class that accepts 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);
  }
}

If I change the load method to public void load(Class clazz) it works fine, can someone tell me how to restrict arguments to load method to be only of subtypes(impl) of MyInterface ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不疑不惑不回忆 2025-01-21 09:43:00

PECS(生产者扩展,消费者超级)就是问题所在。给定一个 List,您当然可以调用 .add(someDouble)。因此,当需要List时,List不能被传递。这种“写入”概念不适用于 Class,但 java 并不“知道”这一点,因此不会让您传递 Class当需要 Class 时。

PECS 有点用词不当。它是从泛型类型(so、List、Class 等)的角度编写的。如果类只生成内容并且不会消耗任何泛型类型(这里就是这种情况),PECS 声明您应该使用 extends

因此,public void load clazz) 就是你想要的。

一些注意事项:

  • 泛型用于链接事物。如果你声明一个泛型变量并在 0 或 1 个地方使用它,那么你就会搞乱或者破解 java 的类型系统(在合法的情况下这是一个好主意,但相当罕见)。假设你在任何地方都不需要那个 T,那你就会搞砸了。只需使用 ? 即可。
  • 混合泛型和类通常是不好的。 Class 可以表示一些东西,例如 intClass c = int.class; is valid java),其中泛型不能(List 不是有效的 java),反之亦然,泛型可以表示该类不能。您不能拥有表示 Listjava.lang.Class 实例(仅限 List - 原始类型)。 Class> 不是一个东西; List.class 不起作用。 List> 确实有效。
  • 不管你怎么想:我知道!我将创建一个接口,使用泛型,并创建一个 Class - 这可能是一个错误。您没有解释是什么让您认为您需要这个。最有可能的是,正确的答案是工厂。本质上,工厂是构造函数的抽象。

PECS (Producer-Extends, Consumer-Super) is the problem. Given a List<Number>, you can, of course, call .add(someDouble). Therefore, a List<Integer> cannot be passed when a List<Number> is required. This 'write' concept just doesn't apply to Class<X>, but java doesn't 'know' that and therefore won't let you pass a Class<SomeImpl> when a Class<TheInterface> is required.

PECS is kind of a misnomer; it's written from the point of view of the genericsed type (so, List, Class, etc). If the class only produces stuff and will not be consuming anything of the generic type, which is the case here, PECS states you should be using extends.

Hence, public void load<Class<? extends MyInterface> clazz) is what you want.

A few notes:

  • Generics serves to link things. If you declare a generic variable and you use it in 0 or 1 places, then you're messing up or hacking java's type system (there are legitimate cases where that's a good idea, but quite rare). Given that you don't need that T anywhere, you'd be messing up. Just use ? instead.
  • Mixing generics and Class is usually bad. There are things Class can represent, such as int (Class<?> c = int.class; is valid java), which generics can't (List<int> is not valid java), and vice versa things generics can represent that class cant. You cannot have an instance of java.lang.Class that represents List<String> (only List - the raw type). Class<List<String>> isn't a thing; List<String>.class does not work. List<List<String>> does work.
  • Whatever made you think: I know! I'll make an interface, use generics, and make a Class<? extends MyInterface> - that was likely a mistake. You didn't explain what made you think you needed this. Most likely, the right answer is a factory. A factory is, essentially, an abstraction for constructors.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文