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
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?))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With