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

kmb7vmvb  于 2021-07-08  发布在  Java
关注(0)|答案(2)|浏览(190)

我有以下类层次结构:

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(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 -构造函数对扩展它的其他类有潜在的副作用。
有没有更好的解决办法?

omqzjyyz

omqzjyyz1#

关于反射和此代码不是最佳实现的标志的评论是真实有效的,每个偶然发现此答案的人都应该阅读并考虑它们。
然而,在我的例子中,不可能完全消除反射,因为 Class 值被传递给另一个不在我控制之下的类-这是否好是另一个问题(我猜,答案是“否”),但不在这个问题的范围内。
我用以下方法解决了我的问题:
删除了 valueType 构造函数中的参数
补充 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;
    }
}

双重演员不好看,我完全知道。然而,这是在一个有限的位置,很明显,这是可以投,它修复了“不能投”的错误。

pgx2nnw8

pgx2nnw82#

所以, MyClass.class 属于类型 Class<MyClass> 不是 Class<MyClass<?>> .
这其实是一个关于反思的问题。
通常解决反射问题的好办法是不使用反射。
我建议取消使用 Class 并替换为所需操作的接口。然后,如果愿意的话,可以在该接口的特定实现中放置反射污点。

相关问题