Vito De Tullio
Vito De Tullio

Reputation: 2121

preserve generics in list elements

I have a class who relies on generics to bind types internally.

class C<T1, T2 extends T1> {
    T1 e1;
    T2 e2;
    /* stuff */
}

In my code I know that, while c.e1 and c.e2 might not have the same class, c.e2 is an instance of a subclass of the class of c.e1.

I need to create a List of these cs, and those elements would not share a common base class. Still, I want to preserve the fact that each element of the List has the attributes bounded between each other.

Ideally I would like to create a List<C<?, ? extends ...>> "but" I don't know any syntax to specify this behaviour. And using a List<C<?, ?>> it seems to me I lost the generics types.

What is the correct way to do this collection?

Upvotes: 1

Views: 104

Answers (2)

Vito De Tullio
Vito De Tullio

Reputation: 2121

I find a solution encoding the types constraint in a custom (un-generic) type.

so now I have these classes:

class MainLogic {
    List<TypeHelper<?,?>> elements = new ArrayList<>();
    <T1, T2 extends T1> void addElement(T1 e1, T2 e2) {
        this.elements.add(new TypeHelper<T1,T2>(e1, e2));
    }
    void logic() {
        for (TypeHelper<?, ?> element: elements)
            element.logicHelper(this);
    }
    <T1, T2 extends T1> void logicHelper(T1 e1, T2 e2) {
        // here finally I have the variables constrained
    }
}

class TypeHelper<T1, T2 extends T1> {
    T1 e1;
    T2 e2;
    void logicHelper(MainLogic ml) {
        ml.logicHelper(e1, e1);
    }
}

Upvotes: 0

Jorn Vernee
Jorn Vernee

Reputation: 33855

Since T2 is bounded in the declaration of C, you will always retain the fact that it is a subtype of T1 even if you use wildcards. i.e. it is a characteristic of C that the second type parameter extends the first.

So you can just use List<C<?, ?>>.

You can already see that this works when you try to bind the generic parameters to type variables. e.g.:

public static <T1, T2> void m(List<C<T1, T2>> list) { ... }
                                         ^^-- Bound mismatch

You would need to use:

public static <T1, T2 extends T1> void m(List<C<T1, T2>> list) {...}

Or:

public static <T1> void m(List<C<T1, ? extends T1>> list) {...}

For the compiler to be happy.

Upvotes: 2

Related Questions