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
可以表示,例如 int
(Class<?> 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>
- 这可能是一个错误。你没有解释是什么让你认为你需要这个。最有可能的是,正确的答案是工厂。工厂本质上是对构造函数的抽象。
我对 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
可以表示,例如int
(Class<?> 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>
- 这可能是一个错误。你没有解释是什么让你认为你需要这个。最有可能的是,正确的答案是工厂。工厂本质上是对构造函数的抽象。