如何使用 Java 泛型解决这种情况?

How can I resolve this situation with Java Generics?

我有以下 class 层次结构:

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 有几个子classes 和几个容器classes 有一些子classes 作为valueType,例如

public class IntObject extends MyObject<Integer> {}
public class IntContainer extends MyObjectContainer<IntObject> {
    public IntContainer() {
        super(IntObject.class);
    }
}

现在我需要实现一个容器,尽管它与 MyObject.

的一组混合子classes 一起工作
public class AllObjectContainer extends MyObjectContainer<MyObject<?>> {
    public AllObjectContainer() {
        super(MyObject.class); // compile error here
    }
}

这不会编译,因为“构造函数 MyObjectContainer(Class) 未定义”。将“MyObject.class”转换为“Class>”是不可能的。

为了解决这个问题,我可以使用原始类型:

  1. public class AllObjectContainer extends MyObjectContainer<MyObject<?>>更改为public class AllObjectContainer extends MyObjectContainer<MyObject>

由于类型擦除,这会产生后果,所以我不喜欢这个解决方案。

或者我可以通过

启用投射
  1. protected MyObjectContainer(Class<T> valueType) { 更改为 protected MyObjectContainer(Class<? extends T> valueType) {(添加 ? extends
  2. super(MyObject.class)更改为super((Class<? extends MyObject<?>>) MyObject.class)

此方法有效,但转换被标记为未检查并且更改 MyMiddleContainer-构造函数对扩展它的其他 class 有潜在的副作用。

有没有更好的解决方案?

所以,MyClass.classClass<MyClass> 类型而不是 Class<MyClass<?>>

这真是一道关于反射的题

通常解决反射问题的好办法就是不使用反射。

我建议删除 Class 的使用并替换为您想要的操作界面。然后,如果您愿意,您可以在该接口的特定实现中放置反射污秽。

关于反射的评论和这段代码不是最佳实现的标志是真实有效的,每个偶然发现这个答案的人应该阅读并考虑它们

然而,在我的例子中,完全摆脱反射是不可能的,因为 Class 值被传递给另一个不受我控制的 class - 无论是好不好是另外一题(我猜,答案是'no'),但不在本题范围内

我通过以下方式解决了我的问题:

  1. 从构造函数中删除了 valueType 参数
  2. protected abstract Class<T> getValueType(); 添加到 MyParentContainer

然后我通过以下方式实现了该方法:

public class IntContainer extends MyObjectContainer<IntObject> {
    protected Class<T> getValueType() {
        return IntObject.class;
    }
}

public class AllObjectContainer extends MyObjectContainer<MyObject<?>> {
    protected Class<T> getValueType() {
        return (Class<MyObject<?>>) (Class<?>) MyObject.class;
    }
}

双重演员阵容不好看,我完全知道这一点。但是在一个密闭的地方,显然是可以施法的,修复了“不能施法”的错误。