Additional Bounds


It is possible to specify additional bounds, or more than one type, in an extends clause. While the first constraint can be either a class or interface, subsequent constraints must be interface types. For example:

 public static    <T extends Iterable&Comparable<T>> void iterateAndCompare(T t) 

By using additional bounds, you are constraining the parameter passed to implement more than one interface. In the example, the object passed in must implement both the Iterable and Comparable interfaces. This is not normally something you want to do; additional bounds were introduced largely to solve issues of backward compatibility (see below).

If a method requires that an object behave as two different types, it intends for that method to do two different kinds of things to that object. In most cases, this will be a violation of the Single-Responsibility Principle, which is as applicable to methods as it is to classes. There will always be exceptions, of course, but before using additional bounds for this reason, see if you can decompose the method in question.

The more legitimate reason to use additional bounds is demonstrated by code in the Collections class. The Collections class contains static utility methods for operating on collection objects; it includes a method named max that returns the largest element in a collection. Under earlier versions of Java, the signature of max was:

 public static Object max(Collection c) 

The passed-in collection could hold any type of object, but the max method depended upon the collection holding objects that implemented the Comparable interface. An initial stab at a solution using generics could insist that the collection hold Comparable objects:

 public static    <T extends Comparable<? super T>> T max(Collection<? extends T> c) 

Paraphrased, this signature says: max takes a collection of objects of any type and that that type must implement the Comparable interface, which in turn must be bound to the type or supertype of elements stored in the collection. The problem is that after erasure, this results in a different signature for the max method:

 public static Comparable max(Collection c) 

Instead of returning an Object reference, max would now return a Comparable reference. The change in signature would break existing compiled code that used the max method, killing compatibility. Using additional bounds effectively solves the problem:

 public static    <T extends Object&Comparable<? super T>>    T max(Collection<? extends T> c) 

Per J2SE specification, a type variable gets erased to its leftmost boundObject in this example, and not Comparable. The max method now returns an Object reference but also defines the additional constraint that the collection objects must implement the appropriate Comparable interface.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net