代码改变世界

Effective Java 23 Don't use raw types in new code

2014-03-17 10:42  小郝(Kaibo Hao)  阅读(795)  评论(0编辑  收藏  举报

Generic types advantage

  1. Parameterized type can provide erroneous check in compile time.

    // Parameterized collection type - typesafe

    private final Collection<Stamp>stamps = ... ;

       

  2. You no longer have to cast manually when removing elements from collections.

    // for-each loop over a parameterized collection - typesafe

    for (Stamp s : stamps) { // No cast

    ... // Do something with the stamp

    }

    or a traditional forloop:

    // for loop with parameterized iterator declaration - typesafe

    for (Iterator<Stamp> i = stamps.iterator(); i.hasNext(); ) {

    Stamp s = i.next(); // No cast necessary

    ... // Do something with the stamp

    }

   

Note

If you use raw types, you lose all the safety and expressiveness benefits of generics.

You lose type safety if you use a raw type like List, but not if you use a parameterized type like List<Object>.

   

// Uses raw type (List) - fails at runtime!

public static void main(String[] args) {

List<String> strings = new ArrayList<String>();

unsafeAdd(strings, new Integer(42));

String s = strings.get(0); // Compiler-generated cast

}

private static void unsafeAdd(List list, Object o) {

list.add(o);

}

   

This program compiles, but because it uses the raw type List, you get a warning:

Test.java:10: warning: unchecked call to add(E) in raw type List

list.add(o);

^

if you run the program, you get a ClassCastException when the program tries to cast the result of the invocation strings.get(0) to a String . This is a compiler-generated cast, so it's normally guaranteed to succeed, but in this case we ignored a compiler warning and paid the price.

   

unbounded wildcard types - Set<?>

If you want to use a generic type but you don't know or care what the actual type parameter is, you can use a question mark instead.

   

// Unbounded wildcard type - typesafe and flexible

static int numElementsInCommon(Set<?> s1, Set <?> s2) {

int result = 0;

for (Object o1 : s1)

if (s2.contains(o1))

result++;

return result;

}

   

Name

Example

Feature

Disadvantage

Raw type

List

Can add anything

No type security check.

Generic type

List<Object>

Provide type check.

Generic type information is erased at runtime (Item 25) which means that List<String>.class and List<?> are illegal.

Unbounded wildcard type

List<?>

You can't put any element (other than null) into a Collection<?> but null.

  

   

This is the preferred way to use the instanceof operator with generic types

// Legitimate use of raw type - instanceof operator

if (o instanceof Set ) { // Raw type

Set<?> m = (Set<?>) o; // Wildcard type

...

}

   

Summary

Raw types can lead to exceptions at runtime, so don't use them in new code;

Set<Object> is a parameterized type representing a set that can contain objects of any type;

Set<?> is a wildcard type representing a set that can contain only objects of some unknown type, and Set is a raw type, which opts out of the generic type system. The first two are safe and the last is not.

   

Term

Example

Item

Parameterized type

List<String>

Item 23

Actual type parameter

String

Item 23

Generic Type List<E>

List<E>

Item 23

Formal type parameter

E

Item 23

Unbounded wildcard type

List<?>

Item 23

Raw type

List

Item 23

Bounded type parameter

<E extends Number>

Item 26

Recursive type bound

<T extends Comparable<T>>

Item 27

Bonded wildcard type

List<? Extends Number>

Item 28

Generic method

Static <E> List<E> asList(E[] a)

Item 27

Type token

String.class

Item 29