Java递归泛型和通配符

3

你好,我有一个关于Java和使用递归泛型通配符的问题。我有以下接口:

public interface Recursive<R extends Recursive<R>> {}

还有一个使用递归接口的接口

public interface Use<R extends Recursive<R>> {}

现在我有一个界面看起来像这样:
public interface Base<R extends Recursive<R>> {
    Use<R>[] getUses();
}

根据这个类,我希望有一个派生类,使用类似通配符的方法。
public class Derived extends Base<Recursive<?>> {
    Use<?>[] getUses();
}

这是不允许的,但我该如何表达我的泛型类型是适用于所有符合条件的内容呢?


1
你的派生类想要做什么?你的代码能通过编译吗? - Tim Biegeleisen
Derived extends Base<Recursive> 应该就足够了。 - Olivier Grégoire
但是我得到了一个警告,因为我使用了原始类型,有没有一种方法可以避免这个警告? - MZuenni
你可能想要的是 class Derived extends Base<Derived> - newacct
此外,这个递归边界很可能是不必要的。 - newacct
2个回答

0
问题在于Recursive< ? >不满足Base类型参数的约束条件。
如果您想扩展Base< R >,则必须为R提供一个也是Recursive< R >的东西。Recursive< ? >不够好,因为编译器无法确定Recursive< ? > extends Recursive< Recursive< ? > >
扩展未知类型的Base并没有真正意义,但您可以声明一个异构集合。
Collection< Base< ? > > cb; // ok for some reason
Collection< Base< Recursive< ? > > > cbr; // not ok!

从您的评论中我们知道Base的样子。
public abstract class Base< R extends Recursive< R > > {
    public abstract R[] foo();
}

对于每个符合条件的R,你当然可以这样做

public class Derived< R extends Recursive< R > > extends Base< R > {
    @Override public R[] foo() {
        return ( R[] )new Object[] { r1, r2 };
    }
}

但从您的评论中并不清楚这是否是您想要的。您知道您想让Derived使用哪个特定的R吗?

编辑:以下代码可以编译通过,是否满足您的需求?

interface Recursive< R extends Recursive< R > > {}
abstract class Base< R extends Recursive< ? extends R > > {
    abstract public R[] foo();
}
class Derived extends Base< Recursive< ? > > {
    public Recursive< ? >[] foo() { return null; }
}

编辑2 调整原帖更改:

interface Recursive< R extends Recursive< R > > {}
interface Use< R extends Recursive< ? extends R > > {}
abstract class Base< R extends Recursive< ? extends R > > {
    abstract public Use< R >[] foo();
}
class Derived extends Base< Recursive< ? > > {
    @Override public Use< Recursive< ? > >[] foo() { return null; }
}

在基类中有一个应该返回 R 数组的方法,在派生类中我需要返回两个实现给定接口的不同对象... 所以这两个对象的超类都是 Recursive,我试图返回一个数组... - MZuenni
在我的情况下,派生类不应该是通用的,因为此时我知道哪些值属于我需要返回的数组。问题是我尝试返回的两个值属于不同的类。所以我知道我需要返回这样的数组:new Recursive<?>[]{},但是我需要将哪个参数插入到基类的泛型中,以便在返回Recursive<?>[]时正确地覆盖该方法呢? - MZuenni
这两种类型有没有共同的超类? - Judge Mental
@MZuenni,我已经编辑了我的回答,请看看是否适用于你的情况。 - Judge Mental
我已经让这个问题变得更加复杂,无法按照我想要的方式使其工作...他们唯一共同的超类是它们都实现的递归接口。 - MZuenni

0

你需要在子类中输入(带有正确的界限),否则编译器无法断定类的通配符与方法返回的类型是相同的,这是必要的。

尝试这样做:

public class Derived<R extends Recursive<R>> extends Base<R> {
    Use<R>[] getUses();
}

正如我之前所说,派生类本身不应该是通用的,而是应该使用给定类型实现接口。 - MZuenni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接