Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't a Generic Type Parameter have a lower bound in Java?

I gather that you cannot bind a Java generics type parameter to a lower bound (i.e. using the super keyword). I was reading what the Angelika Langer Generics FAQ had to say on the subject. They say it basically comes down to a lower bound being useless ("not making any sense").

I'm not convinced. I can imagine a use for them to help you be more flexible to callers of a library method that produces a typed result. Imagine a method that created an array list of a user-specified size and filled it with the empty string. A simple declaration would be

public static ArrayList<String> createArrayListFullOfEmptyStrings(int i); 

But that's unnecessarily restrictive to your clients. Why can't they invoke your method like this:

//should compile List<Object> l1 = createArrayListFullOfEmptyStrings(5);  List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5); List<String> l3 = createArrayListFullOfEmptyStrings(5);  //shouldn't compile List<Integer> l4 = createArrayListFullOfEmptyStrings(5); 

At this point I would be tempted to try the following definition:

public static <T super String> List<T> createArrayListFullOfEmptyStrings(int size) {   List<T> list = new ArrayList<T>(size);   for(int i = 0; i < size; i++) {      list.add("");   }   return list; } 

But it will not compile; the super keyword is illegal in this context.

Is my example above a bad example (ignoring what I say below)? Why isn't a lower bound useful here? And if it would be useful, what's the real reason that it is not permitted in Java?

P.S.

I know that a better organization might be something like this:

public static void populateListWithEmptyStrings(List<? super String> list, int size);  List<CharSequence> list = new ArrayList<CharSequence>(); populateListWithEmptyStrings(list, 5); 

Can we for the purpose of this question pretend that due to a requirement, we need to do both operations in one method call?

Edit

@Tom G (justifiably) asks what benefit having a List<CharSequence> would have over a List<String>. For one, nobody said the returned list is immutable, so here's one advantage:

List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5); l2.add(new StringBuilder("foo").append("bar")); 
like image 569
Mark Peters Avatar asked Feb 04 '11 20:02

Mark Peters


People also ask

How are bounds used with generics?

Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class. These are known as bounded-types in generics in Java.

Can a parameterized type have several bounds?

A type parameter can have multiple bounds.

Why do we need bounded type parameters in Java?

There may be times when you want to restrict the types that can be used as type arguments in a parameterized type. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

What is upper bound and lower bound in generics?

Upper-bound is when you specify (? extends Field) means argument can be any Field or subclass of Field. Lower-bound is when you specify (? super Field) means argument can be any Field or superclass of Field. Try following code: Uncomment the code and check if any error comes.


1 Answers

Basically, its not useful enough.

I think your example points out the only advantage of a lower bound, a feature the FAQ calls Restricted Instantiation:

The bottom line is: all that a " super " bound would buy you is the restriction that only supertypes of Number can be used as type arguments. ....

But as the other posts point out, the usefulness of even this feature can be limited.

Due to the nature of polymorphism and specialization, upper bounds are far more useful than lower bounds as described by the FAQ (Access To Non-Static Members and Type Erasure). I suspect the complexity introduced by lower bounds aren't worth its limited value.


OP: I want to add I think you did show it is useful, just not useful enough. Come up with the irrefutable killer use cases and I'll back the JSR. :-)

like image 156
Bert F Avatar answered Sep 23 '22 12:09

Bert F