您的位置:首页 > Web前端

Effective Java 28 Use bounded wildcards to increase API flexibility

2014-03-22 22:06 393 查看
Get and Put Principle

PECS stands for producer-extends(? extends T), consumer-super(? super T).

For maximum flexibility, use wildcard types on input parameters that represent producers or consumers.

// Wildcard type for parameter that serves as an E producer

public void pushAll(Iterable<? extends E> src) {

for (E e : src)

push(e);

}

// Wildcard type for parameter that serves as an E consumer

public void popAll(Collection<? super E> dst) {

while (!isEmpty())

dst.add(pop());

}

Although lists can both consume and produce values, the reduce method uses its list parameter only as an E producer, so its declaration should use a wildcard type that extends E. The parameter f represents a function that both consumes and produces E instances, so a wildcard type would be inappropriate for it. Here's the resulting method declaration:

// Wildcard type for parameter that serves as an E producer

static <E> E reduce(List<? extends E>list, Function<E> f, E initVal)

2. Do not use wildcard types as return types.

public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)

3. If the user of a class has to think about wildcard types, there is probably something wrong with the class's API.

4. Use explicit parameter for the generic method.

Set<Integer> integers = ... ;

Set<Double> doubles = ... ;

Set<Number> numbers = union(integers, doubles);

Set<Number> numbers = Union.<Number>union(integers, doubles);

Always use Comparable<? super T> in preference to Comparable<T>.The same is true of comparators, so you should always use Comparator<? super T> in preference to Comparator<T>.

public static <T extends Comparable<? super T>> T max(List<? extends T> list)

5. If a type parameter appears only once in a method declaration, replace it with a wildcard for its simplify.

// Two possible declarations for the swap method

public static <E> void swap(List<E> list, int i, int j);

public static void swap(List<?> list, int i, int j);

// Use this one instead of first one. But this one will not compile since the one above cannot set an element

// to the list object whose type is List<?> unless the object is null.

// And you should provide clean API list the code below.

public static void swap(List<?> list, int i, int j) {

swapHelper(list, i, j);

}

// Private helper method for wildcard capture

private static <E> void swapHelper(List<E> list, int i, int j) {

list.set(i, list.set(j, list.get(i)));

}

Summary

Using wildcard types in your APIs, while tricky, makes the APIs far more flexible. If you write a library that will be widely used, the proper use of wildcard types should be considered mandatory. Remember the basic rule: producer-extends, consumer-super(PECS). And remember that all comparables and comparators are consumers.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: