Section 17.3. Wrappers


17.3. Wrappers

The Collections class provides wrapper objects that modify the behavior of standard collections classes in one of three waysby synchronizing them, by making them unmodifiable, or by checking the type of elements being added to them. These wrapper objects implement the same interfaces as the wrapped objects, and they delegate their work to them. Their purpose is to restrict the circumstances under which that work will be carried out. These are examples of the use of protection proxies (see Design Patterns by Gamma, Helm, Johnson, and Vlissides, Addison-Wesley), a variant of the Proxy pattern in which the proxy controls access to the real subject.

Proxies can be created in different ways. Here, they are created by factory methods that wrap the supplied collection object in an inner class of Collections that implements the collection's interface. Subsequently, method calls to the proxy are (mostly) delegated to the collection object, but the proxy controls the conditions of the call: in the case of the synchronized wrappers, all method calls are delegated but the proxy uses synchronization to ensure that the collection is accessed by only one thread at a time. In the case of unmodifiable and checked collections, method calls that break the contract for the proxy fail, throwing the appropriate exception.

17.3.1. Synchronized Collections

As we explained in Section 11.5, most of the Framework classes are not thread-safeby designin order to avoid the overhead of unnecessary synchronization (as incurred by the legacy classes Vector and Hashtable). But there are occasions when you do need to program multiple threads to have access to the same collection, and these synchronized wrappers are provided by the Collections class for such situations.

There are six synchronized wrapper factory methods, corresponding to the six pre-Java 6 interfaces of the Collections Framework. (No synchronized wrappers were provided in Java 6 for NavigableSet or NavigableMap. If they had been provided, there would be very few situations in which you would choose them over the thread-safe collections ConcurrentSkipListSet and ConcurrentSkipListMap.)

 <T> Collection<T> synchronizedCollection(Collection<T> c); <T> Set<T> synchronizedSet(Set<T> s); <T> List<T> synchronizedList(List<T> list); <K, V> Map<K, V> synchronizedMap(Map<K, V> m); <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s); <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m); 

The classes that provide these synchronized views are conditionally thread-safe (see Section 11.5); although each of their operations is guaranteed to be atomic, you may need to synchronize multiple method calls in order to obtain consistent behavior. In particular, iterators must be created and used entirely within a code block synchronized on the collection; otherwise, the result will at best be failure with ConcurrentModificationException. This is very coarse-grained synchronization; if your application makes heavy use of synchronized collections, its effective concurrency will be greatly reduced.

17.3.2. Unmodifiable Collections

An unmodifiable collection will throw UnsupportedOperationException in response to any attempt to change its structure or the elements that compose it. This can be useful when you want to allow clients read access to an internal data structure. Passing the structure in an unmodifiable wrapper will prevent a client from changing it. It will not prevent the client from changing the objects it contains, if they are modifiable. In some cases, you may have to protect your internal data structure by providing clients instead with a defensive copy made for that purpose, or by also placing these objects in unmodifiable wrappers.

There are six unmodifiable wrapper factory methods, corresponding to the six major interfaces of the Collections Framework:

 <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) <T> Set<T> unmodifiableSet(Set<? extends T> s) <T> List<T> unmodifiableList(List<? extends T> list) <K, V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m) <T> SortedSet<T> unmodifiableSortedSet(SortedSet<? extends T> s) <K, V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m) 

17.3.3. Checked Collections

Unchecked warnings from the compiler are a signal to us to take special care to avoid run-time type violations. For example, after we have passed a typed collection reference to an ungenerified library method, we can't be sure that it has added only correctly typed elements to the collection. Instead of losing confidence in the collection's type safety, we can pass in a checked wrapper, which will test every element added to the collection for membership of the type supplied when it was created. Section 8.2 shows an example of this technique.

Checked wrappers are supplied for the main interfaces:

 static <E> Collection     checkedCollection(Collection<E> c, Class<E> elementType) static <E> List     checkedList(List<E> c, Class<E> elementType) static <E> Set     checkedSet(Set<E> c, Class<E> elementType) static <E> SortedSet     checkedSortedSet(SortedSet<E> c, Class<E> elementType) static <K, V> Map     checkedMap(Map<K, V> c, Class<K> keyType, Class<V> valueType) static <K, V> SortedMap     checkedSortedMap(SortedMap<K, V> c, Class<K> keyType, Class<V> valueType) 




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