简体   繁体   English

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

[英]How can I resolve this situation with Java Generics?

I have the following class hierarchy:我有以下类层次结构:

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);
    }
}

This works fine so far.到目前为止,这工作正常。 There are several subclasses of MyObject and several container classes having some of those subclasses as valueType , eg MyObject有几个子类和几个容器类,其中一些子类作为valueType ,例如

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

Now I need to implement a container though that works with a mixed set of subclasses of MyObject .现在我需要实现一个容器,尽管它可以与MyObject一组混合子类一起使用。

public class AllObjectContainer extends MyObjectContainer<MyObject<?>> {
    public AllObjectContainer() {
        super(MyObject.class); // compile error here
    }
}

This does not compile, because "The constructor MyObjectContainer<MyObject>(Class) is undefined".这不会编译,因为“构造函数 MyObjectContainer<MyObject>(Class) 未定义”。 Casting `MyObject.class` to `Class>` is not possible.无法将 `MyObject.class` 转换为 `Class>`。

To solve this, I could use raw types:为了解决这个问题,我可以使用原始类型:

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

This has consequences though because of type erasure, so I do not like this solution.由于类型擦除,这会产生后果,所以我不喜欢这个解决方案。

Alternatively I could enable casting by或者,我可以通过以下方式启用投射

  1. Change protected MyObjectContainer(Class<T> valueType) { to protected MyObjectContainer(Class<? extends T> valueType) { (add ? extends )protected MyObjectContainer(Class<T> valueType) {更改为protected MyObjectContainer(Class<? extends T> valueType) { (添加? extends
  2. Change super(MyObject.class) to super((Class<? extends MyObject<?>>) MyObject.class)super(MyObject.class)更改为super((Class<? extends MyObject<?>>) MyObject.class)

This method works, but the cast is marked as unchecked and changing the MyMiddleContainer -Constructor has potential side effects on other classes that extend it.此方法有效,但转换被标记为未选中,更改MyMiddleContainer -Constructor 对扩展它的其他类有潜在的副作用。

Are there any better solutions?有没有更好的解决方案?

So, MyClass.class is of type Class<MyClass> not Class<MyClass<?>> .因此, MyClass.class的类型为Class<MyClass>而不是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.我建议删除Class的使用并替换为您想要的操作的接口。 You can then, if you wish, place reflection nastiness within a particular implementation of that interface.然后,如果您愿意,您可以将反射问题置于该接口的特定实现中。

The comments about reflection and that this code is not the sign of the best implementation are true and valid and everyone who stumbles upon this answer should read and consider them .关于反射的评论以及此代码不是最佳实现的标志是真实有效的,每个偶然发现此答案的人都应该阅读并考虑它们

Yet, in my case, it was not possible to get rid of the reflection altogether, because the Class value was passed on to another class that is not under my control - whether that is good is another question (I guess, the answer is 'no'), but not in the scope of this question.然而,在我的情况下,不可能完全摆脱反射,因为Class值被传递给另一个不受我控制的类 - 这是否好是另一个问题(我猜,答案是'否'),但不在此问题的范围内。

I solved my problem in the following way:我通过以下方式解决了我的问题:

  1. removed the valueType parameter from the constructor从构造函数中删除了valueType参数
  2. added protected abstract Class<T> getValueType();添加了protected abstract Class<T> getValueType(); to MyParentContainer到我的MyParentContainer

Then I implemented the method in the following ways:然后我通过以下方式实现了该方法:

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;
    }
}

The dual cast is not pretty, I am totally aware of that.双重演员并不漂亮,我完全意识到这一点。 Yet it is in a confined location, it is obvious that it is possible to cast and it fixes the "cannot cast" error.然而它在一个封闭的位置,很明显可以投射并且它修复了“无法投射”的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM