简体   繁体   中英

Java recursive Generic and Wildcard

Hello i have a question about Java and using wildcard with recursive generics. I have the following interface

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

and another intrface which uses the recursive interface

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

now i have interface which looks like this

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

and based on that class i want a derived class which uses a wildcard like that

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

which isnt allowed but how can i manage to say that my generic type is everything that fits?

The problem is that Recursive< ? > Recursive< ? > doesn't satisfy the constraint on Base 's type parameter.

If you want to extend Base< R > you have to supply something for R which is also a Recursive< R > . Recursive< ? > Recursive< ? > is not good enough because the compiler can't figure out that Recursive< ? > extends Recursive< Recursive< ? > > Recursive< ? > extends Recursive< Recursive< ? > > Recursive< ? > extends Recursive< Recursive< ? > > .

It doesn't really make sense to extend a Base of unknown type, but you can declare a heterogeneous collection of them:

Collection< Base< ? > > cb; // ok for some reason
Collection< Base< Recursive< ? > > > cbr; // not ok!

From your comment we know Base looks like

public abstract class Base< R extends Recursive< R > > {
    public abstract R[] foo();
}

For each qualifying R you can of course do

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

but it's not clear from your comment that this is what you want. Do you know what the specific R is that you want Derived to use?

EDIT the following compiles. would that suffice?

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

EDIT 2 Adjusting for the change to the original post:

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

You need to type (with the right bound) your subclass, otherwise the compiler can't assert that the wildcard of the class is the same type as what your method returns, which is required.

Try this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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