So the other day I got a question from a colleague at work about a syntax. He is working on a new API and would like to make use of generics. He drew three different declarations
public Bus getBus();
public Bus<? extends T> getBus();
public Bus <? super T> getBus();
I scratched my head and said I defiantly knew about the first two. First is the Exact Bound, meaning T and only T, no super type of T (Object) or derived version of T (T'). Will be returned by the getBus() property.
Second option, ? extends T, meaning T and all it's derivatives (T', T'') etc. But not Object or any super type of T. What normally is declared as Upper Bound. All types that implements or extends T qualify as type argument.
The third one, I'd never seen before. The third one didn't make any sense. I asked him if it compiled and he answered back that it did.
Logically the syntax would imply that anything that T is derived of would be allowed to be returned by the method. Reasonably this syntax must be called Lower Bound as the covariant version of Bus is normally called Upper Bound.
The other interesting part of the syntax is that it only seems to apply to the initialization of a variable/field/return i.e. a reference. As soon as the reference is used the Upper Bound rules apply. Example take the following hierarchy:
public static class Super
{
}
public static class Foo extends Super
{
}
public static class Bar extends Foo
{
}
Then the following does not compile
List <? super T> Foo list = new ArrayList
list.add(new Super()); // error
list.add(new Object()); // error
Which the syntax List<? super Foo> list seems to imply. That, whatever is being assigned to list needs to be instantiated with a super type of T (in the example Foo). So it cannot be assigned an ArrayList of Bar for example.
list = new ArrayList<Bar>();
Does not compile! When using a Lower bound generics however like the supplied type must be of the same type or derivative of the type.
No comments:
Post a Comment