Java 限制 Class<>到特定类型
我对 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
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) 我的界面?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
PECS(生产者扩展,消费者超级)就是问题所在。给定一个
List
,您当然可以调用.add(someDouble)
。因此,当需要List
时,List
不能被传递。这种“写入”概念不适用于Class
,但 java 并不“知道”这一点,因此不会让您传递Class
当需要Class
时。PECS 有点用词不当。它是从泛型类型(so、List、Class 等)的角度编写的。如果类只生成内容并且不会消耗任何泛型类型(这里就是这种情况),PECS 声明您应该使用
extends
。因此,
public void load clazz)
就是你想要的。一些注意事项:
?
即可。Class
可以表示一些东西,例如int
(Class c = int.class;
is valid java),其中泛型不能(List
不是有效的 java),反之亦然,泛型可以表示该类不能。您不能拥有表示List
的java.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, aList<Integer>
cannot be passed when aList<Number>
is required. This 'write' concept just doesn't apply toClass<X>
, but java doesn't 'know' that and therefore won't let you pass aClass<SomeImpl>
when aClass<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:
?
instead.Class
is usually bad. There are thingsClass
can represent, such asint
(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 ofjava.lang.Class
that representsList<String>
(only List - the raw type).Class<List<String>>
isn't a thing;List<String>.class
does not work.List<List<String>>
does work.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.