Why can't you have multiple interfaces in a bounded wildcard generic?
Interestingly, interface java.lang.reflect.WildcardType
looks like it supports both upper bounds and lower bounds for a wildcard arg; and each can contain multiple bounds
Type[] getUpperBounds();
Type[] getLowerBounds();
This is way beyond what the language allows. There's a hidden comment in the source code
// one or many? Up to language spec; currently only one, but this API
// allows for generalization.
The author of the interface seems to consider that this is an accidental limitation.
The canned answer to your question is, generics is already too complicated as it is; adding more complexity might prove to be the last straw.
To allow a wildcard to have multiple upper bounds, one has to scan through the spec and make sure the entire system still works.
One trouble I know would be in the type inference. The current inference rules simply can't deal with intersection types. There's no rule to reduce a constraint A&B << C
. If we reduced it to
A<<C
or
A<<B
any current inference engine has to go through major overhaul to allow such bifurcation. But the real serious problem is, this allows multiple solutions, but there's no justification to prefer one over another.
However, inference is not essential to type safety; we can simply refuse to infer in this case, and ask programmer to explicitly fill in type arguments. Therefore, difficulty in inference is not a strong argument against intercection types.
From the Java Language Specification:
4.9 Intersection Types An intersection type takes the form T1 & ... & Tn, n>0, where Ti, 1in, are type expressions. Intersection types arise in the processes of capture conversion (§5.1.10) and type inference (§15.12.2.7). It is not possible to write an intersection type directly as part of a program; no syntax supports this. The values of an intersection type are those objects that are values of all of the types Ti, for 1in.
So why is this not supported? My guess is, what should you do with such a thing? - let's suppose it were possible:
List<? extends A & B> list = ...
Then what should
list.get(0);
return? There's no syntax to capture a return value of A & B
. Adding something into such a list would not be possible either, so it's basically useless.
No problem... just declare the type you need in the method signature.
This compiles:
public static <T extends A & B> void main(String[] args) throws Exception
{
AandBList<AandB> foo = new AandBList<AandB>(); // This works fine!
foo.getList().add(new AandB());
List<? extends A> bar = new LinkedList<AandB>(); // This is fine too
List<T> foobar = new LinkedList<T>(); // This compiles!
}