Java nested wildcard bound types multiple times or as generic type parameter
Asked Answered
S

1

6

I have a class with a bounded type parameter with nested wildcard bounded types. In the class I need to use the types of the bound nested parameters in multiple methods. Is there a way to define the wildcard bounded type as a generic type parameter instead or assign it to a generic variable name so that it can easily be referenced in multiple places?

The way the class is implemented now is like

    class AbstractManager<F extends Filter<? extends Criteria<? extends Type>>>
    {
       protected void setFilter(F filter)
       {
         setCriteria(f.getCriteria());
       }

       protected <T extends Criteria<? extends Type>> void setCriteria(List<T> criteria)
       {   
       }

       protected <T extends Criteria<? extends Type>> void doSomethingWithCriteria(List<T> criteria)
       {
          ...
       }
    }

which does not bound actually restrict the type of the list to the type of the Filter but is good enough in our situation. Ideally the type of the list would be restricted to the type of the filter using a construct that could bind the inferred type of the filter to a name much like a bounded type parameter on a method but at the class level instead.

Basically I would like to do something like

    class <G extends Criteria<? extends Type> AbstractManager<F extends Filter<G>>

From what I know and can find, this is not possible, but I was hoping that maybe there was an obscure feature or new feature in java 7 that would make this possible. I know it is possible to specify a second type parameter like

    class AbstractManager<F extends Filter<G>, G extends Criteria<? extends Type>>

but I do not want the child classes to have to specify G when the compiler can determine it.

The only possible option/solution I have been able to find is to have a shallow subclass with factory methods given in the solution to this question Nested Type Parameters in Java and in Java generics - use same wildcard multiple times

Startling answered 5/7, 2013 at 16:51 Comment(1)
Can you give a sample of what final result you desire?Hildehildebrand
P
1

If I understand what you intend to do, it would change the semantics of your class. Right now in your current class, you could have for example:

class T1 extends Type {}
class T2 extends Type {}
class C1 extends Criteria<T1> {}
class C2 extends Criteria<T2> {}
class C3 extends Criteria<T2> {}
class F1 extends Filter<C1> {}
class Manager extends AbstractManager<F1> {}

And then, even though Manager is based on F1, some user code would be perfectly legal if it did:

Manager m = new Manager();
C2 c2 = new C2();
C3 c3 = new C3();
m.setCriteria(Arrays.asList(new C2[]{c2});
m.doSomethingWithCriteria(Arrays.asList(new C3[]{c3});

I don't know if it was your intent, but it is legal (from a compiler point of view). However, if you were somehow able to name that wildcard type, by using that name in your methods you would constrain the user of your class to use the same type in all methods. In other words, in my example the methods would have to be called with lists of C1.

As a conclusion, if you want the flexibility that your example has, you need to repeat the wildcard; but if you want a constraint that the methods use the same criteria as the filter of the manager, then you actually gave the solution:

class AbstractManager<F extends Filter<G>, G extends Criteria<? extends Type>>

(or create a dedicated sub-type to avoid the repeating, as you mentioned (anything that you don't like with that?))

Personification answered 28/3, 2014 at 9:0 Comment(2)
You are right the current implementation allows different types in setCriteria/doSomethingWithCriteria than what is defined in the Filter, hence the problem and the need for some other construct/mechanism such as naming the constraint at the class level like class <G extends Criteria<? extends Type> or which is solved non-ideally with the solution of having a second parameter. I should have made this more clear in the question.Startling
OK, then I think the short answer to your question is unfortunately: 'No'... And you're right, a less verbose mechanism would be nice. I think the best would be able to name the wildcard even within the description. For example: class AbstractManager<F extends Filter<C extends Criteria<T extends Type>> with the ability to re-use F, C and T anywhere in the class. You can always suggest it to the community for Java 9 :)Personification

© 2022 - 2024 — McMap. All rights reserved.