Section 3.6. Multiple Bounds


3.6. Multiple Bounds

We have seen many examples where a type variable or wildcard is bounded by a single class or interface. In rare situations, it may be desirable to have multiple bounds, and we show how to do so here.

To demonstrate, we use three interfaces from the Java library. The Readable interface has a read method to read into a buffer from a source, the Appendable interface has an append method to copy from a buffer into a target, and the Closeable interface has a close method to close a source or target. Possible sources and targets include files, buffers, streams, and so on.

For maximum flexibility, we might want to write a copy method that takes any source that implements both Readable and Closeable and any target that implements both Appendable and Closeable:

 public static <S extends Readable & Closeable,                T extends Appendable & Closeable>   void copy(S src, T trg, int size)   throws IOException {   CharBuffer buf = CharBuffer.allocate(size);   int i = src.read(buf);   while (i >= 0) {     buf.flip();  // prepare buffer for writing     trg.append(buf);     buf.clear();  // prepare buffer for reading     i = src.read(buf);   }   src.close();   trg.close(); } 

This method repeatedly reads from the source into a buffer and appends from the buffer into a target. When the source is empty, it closes both the source and the target. The first line specifies that S ranges over any type that implements both Readable and Closeable, and that T ranges over any type that implements Appendable and Closeable. When multiple bounds on a type variable appear, they are separated by ampersands. (You cannot use a comma, since that is already used to separate declarations of type variables.)

For example, this method may be called with two files as source and target, or with the same two files wrapped in buffers as source and target:

 int size = 32; FileReader r = new FileReader("file.in"); FileWriter w = new FileWriter("file.out"); copy(r,w,size); BufferedReader br = new BufferedReader(new FileReader("file.in")); BufferedWriter bw = new BufferedWriter(new FileWriter("file.out")); copy(br,bw,size); 

Other possible sources include FilterReader, PipedReader, and StringReader, and other possible targets include FilterWriter, PipedWriter, and PrintStream. But you could not use StringBuffer as a target, since it implements Appendable but not Closeable

If you are picky, you may have spotted that all classes that implement both Readable and Closeable are subclasses of Reader, and almost all classes that implement Appendable and Closeable are subclasses of Writer. So you might wonder why we don't simplify the method signature like this:

 public static void copy(Reader src, Writer trg, int size) 

This will indeed admit most of the same classes, but not all of them. For instance, PrintStream implements Appendable and Closeable but is not a subclass of Writer. Furthermore, you can't rule out the possibility that some programmer using your code might have his or her own custom class that, say, implements Readable and Closeable but is not a subclass of Reader.

When multiple bounds appear, the first bound is used for erasure. We saw a use of this earlier in Section 3.2:

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

Without the highlighted text, the erased type signature for max would have Comparable as the return type, whereas in legacy libraries the return type is Object. Maintaining compatibility with legacy libraries is further discussed in Chapter 5 and Section 8.4.




Java Generics and Collections
Java Generics and Collections
ISBN: 0596527756
EAN: 2147483647
Year: 2006
Pages: 136

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