Java - 使用类型参数初始化 class 时出现问题
Java - issue initializing class with type parameters
我在使用类型参数初始化 class 时遇到问题。这似乎是 Java 类型推断的一个缺点,我想知道是否有解决此问题的方法或更好的方法来实现此目的。
public class ParentModel {}
public class ChildModel extends ParentModel {}
public class Service<E extends ParentModel, T extends Collection<E>> {
private Class<T> classOfT;
private Class<E> classOfE;
public Service(Class<E> classOfE, Class<T> classOfT) {
this.classOfE = classOfE;
this.classOfT = classOfT;
}
}
public class BusinessLogic {
public void someLogic() {
Service<ChildModel, ArrayList<ChildModel>> service = new
Service<ChildModel, ArrayList<ChildModel>>(ChildModel.class, ArrayList.class);
}
}
编译时错误在 BusinessLogic::someLogic()
:
The constructor Service<ChildModel, ArrayList<ChildModel>>(Class<ChildModel>, Class<ArrayList>) is undefined
编译为Java 7.
因为没有ArrayList<ChildModel>.class
这样的东西,所以没有优雅的方法来解决这个问题。
正如 Yassin 所提到的,您可以将原始类型传递给您的构造函数,如下所示:
Service<ChildModel, ArrayList<ChildModel>> s1 =
new Service<>(ChildModel.class, (Class) ArrayList.class)
与您的调用不同的是,这里我们使用的是原始类型 Class
,而在您的示例中使用的是类型 Class<ArrayList>
(因此这不是错误)。
另一种选择是从实际实例中获取类型:
Class<ArrayList<ChildModel>> fromObj =
(Class<ArrayList<ChildModel>>) new ArrayList<ChildModel>(0).getClass();
这更冗长,但我更喜欢原始类型(在这两种情况下您都会收到编译器警告)
因为Java中的泛型实现了"by erasure",所以没有Class<ArrayList<ChildModel>>>
,只有一个Class<ArrayList>
。
您可以做的是允许超类型。
Class<? super T> classOfT;
Class<? super E> classOfE;
public Service(Class<? super E> classOfE, Class<? super T> classOfT) {
或者,您可以双重施放 class:
Class<ArrayList<Integer>> clazz =
(Class<ArrayList<Integer>>) (Class<? super ArrayList>)
ArrayList.class;
但请注意:class 只是 ArrayList
- Java 不会在运行时对泛型 执行额外的类型检查。自己看看:
ArrayList<Integer> a1 = new ArrayList<>();
ArrayList<Double> a2 = new ArrayList<>();
System.out.println(a1.getClass() == a2.getClass());
和一样class。在运行时,泛型几乎消失了
我在使用类型参数初始化 class 时遇到问题。这似乎是 Java 类型推断的一个缺点,我想知道是否有解决此问题的方法或更好的方法来实现此目的。
public class ParentModel {}
public class ChildModel extends ParentModel {}
public class Service<E extends ParentModel, T extends Collection<E>> {
private Class<T> classOfT;
private Class<E> classOfE;
public Service(Class<E> classOfE, Class<T> classOfT) {
this.classOfE = classOfE;
this.classOfT = classOfT;
}
}
public class BusinessLogic {
public void someLogic() {
Service<ChildModel, ArrayList<ChildModel>> service = new
Service<ChildModel, ArrayList<ChildModel>>(ChildModel.class, ArrayList.class);
}
}
编译时错误在 BusinessLogic::someLogic()
:
The constructor Service<ChildModel, ArrayList<ChildModel>>(Class<ChildModel>, Class<ArrayList>) is undefined
编译为Java 7.
因为没有ArrayList<ChildModel>.class
这样的东西,所以没有优雅的方法来解决这个问题。
正如 Yassin 所提到的,您可以将原始类型传递给您的构造函数,如下所示:
Service<ChildModel, ArrayList<ChildModel>> s1 =
new Service<>(ChildModel.class, (Class) ArrayList.class)
与您的调用不同的是,这里我们使用的是原始类型 Class
,而在您的示例中使用的是类型 Class<ArrayList>
(因此这不是错误)。
另一种选择是从实际实例中获取类型:
Class<ArrayList<ChildModel>> fromObj =
(Class<ArrayList<ChildModel>>) new ArrayList<ChildModel>(0).getClass();
这更冗长,但我更喜欢原始类型(在这两种情况下您都会收到编译器警告)
因为Java中的泛型实现了"by erasure",所以没有Class<ArrayList<ChildModel>>>
,只有一个Class<ArrayList>
。
您可以做的是允许超类型。
Class<? super T> classOfT;
Class<? super E> classOfE;
public Service(Class<? super E> classOfE, Class<? super T> classOfT) {
或者,您可以双重施放 class:
Class<ArrayList<Integer>> clazz =
(Class<ArrayList<Integer>>) (Class<? super ArrayList>)
ArrayList.class;
但请注意:class 只是 ArrayList
- Java 不会在运行时对泛型 执行额外的类型检查。自己看看:
ArrayList<Integer> a1 = new ArrayList<>();
ArrayList<Double> a2 = new ArrayList<>();
System.out.println(a1.getClass() == a2.getClass());
和一样class。在运行时,泛型几乎消失了