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.
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.
相关文章推荐
- Effective Java 37 Use marker interfaces to define types
- elasticsearch install and how to use javaapi
- How to use java Properties API -- read and write
- EffectiveJava(28)怎么利用有限制的通配符类型来提升API的灵活性
- Effective Java 19 Use interfaces only to define types
- Use Java Mail API to Send Email
- Effective Java 21 Use function objects to represent strategies
- Use Java Mail API to Send Email
- 求解?Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use
- IDEA 编译错误:java: try-with-resources is not supported in -source 1.6 (use -source 7 or higher to enable try-with-resources)
- java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this a
- What is volatile variable in Java - When to use
- Use Java reflection to find classes that implement an interface from a package
- httpurlconnection - How to use java.net.URLConnection to fire and handle HTTP requests? - Stack Overflow
- zabbix-Java library to access Zabbix API
- OpenMediaEngine - Very easy to use API for media streaming
- How to use Berkeley DB Java Edition
- 【tomcat】启动报错:Failed to initialize end point associated with ProtocolHandler ["http-apr-8080"] java.lang.Exception: Socket bind failed 和java.net.BindException: Address already in use: JVM_Bind错误解决
- Apache Project:POI-HSSF - Java API To Access Microsoft Excel Format Files(ZT)
- Effective Java 41 Use overloading judiciously