java - 如何使用 Java 泛型解决这种情况?
问题描述
我有以下类层次结构:
public abstract class MyParentObject {}
public abstract class MyObject<T> extends MyParentObject {}
public abstract class MyParentContainer<T extends MyParentObject> {
private Class<T> valueType;
protected MyParentContainer(Class<T> valueType) {
this.valueType = valueType;
}
}
public abstract class MyObjectContainer<T extends MyObject<?>> extends MyParentContainer<T> {
protected MyObjectContainer(Class<T> valueType) {
super(valueType);
}
}
到目前为止,这工作正常。有几个子类MyObject
和几个容器类,其中一些子类为valueType
,例如
public class IntObject extends MyObject<Integer> {}
public class IntContainer extends MyObjectContainer<IntObject> {
public IntContainer() {
super(IntObject.class);
}
}
现在我需要实现一个容器,尽管它适用于MyObject
.
public class AllObjectContainer extends MyObjectContainer<MyObject<?>> {
public AllObjectContainer() {
super(MyObject.class); // compile error here
}
}
这不会编译,因为“构造函数 MyObjectContainer<MyObject>(Class) 未定义”。将 `MyObject.class` 转换为 `Class>` 是不可能的。
为了解决这个问题,我可以使用原始类型:
- 更改
public class AllObjectContainer extends MyObjectContainer<MyObject<?>>
为public class AllObjectContainer extends MyObjectContainer<MyObject>
尽管由于类型擦除,这会产生后果,所以我不喜欢这种解决方案。
或者我可以通过
- 更改
protected MyObjectContainer(Class<T> valueType) {
为protected MyObjectContainer(Class<? extends T> valueType) {
(添加? extends
) - 更改
super(MyObject.class)
为super((Class<? extends MyObject<?>>) MyObject.class)
此方法有效,但强制转换被标记为未检查,并且更改MyMiddleContainer
-Constructor 对扩展它的其他类有潜在的副作用。
有没有更好的解决方案?
解决方案
So, MyClass.class
is of type Class<MyClass>
not Class<MyClass<?>>
.
This is really a question about reflection.
The usual good solution to the problem of reflection is not to use reflection.
I suggest removing the use of Class
and replace with an interface of the operations you want. You can then, if you wish, place reflection nastiness within a particular implementation of that interface.
推荐阅读
- perl - 将 Markdown 文件中包含特定路径模式的所有节标题转换为不同的格式
- java - 通过spring boot java本地访问时,AWS Elastic Cache(Redis)连接失败(jedis连接错误)
- r - 在 Shiny 中,“闭包”类型的对象不是子集,尽管使用了括号
- java - 如何一次选择 1 个单选按钮(RecyclerView)?
- sql - 加入窗口函数以显示与 ID 相关的下一个日期
- python - 在 Flask 中显示 .txt 文件
- prometheus - Prometheus Labeldrop 操作背后的基本原理
- google-drive-api - 如何使用python读取谷歌驱动器中特定目录中的所有文件?
- android - 将 MaterialAlertDialogBuilder 与材质主题一起使用
- spring - 用于postgresql 的H2 内存数据库| 错误代码:90051