Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
You'll usually see generics when dealing with collections of some kind. In fact, the Collections Framework (which we'll call Collections from now on) was a major motivation behind the introduction of generic types to the Java language because generics enable compile-time checking of the type safety of operations on a collection. When you specify the type of object stored in a collection:
- The compiler can verify any operation that adds an object to the collection.
- The type of an object retrieved from a collection is known, so there's no need to cast it to a type.
Type Parameter Conventions
You have already seen the angle bracket and single letter notation used to represent a type parameter. By convention, a type parameter is a single, uppercase letter this allows easy identification and distinguishes a type parameter from a class name. The most common type parameters you will see are:
<T>
Type<S>
for Type, when T is already in use<E>
Element (used extensively by the Java Collections Framework)<K>
Key<V>
Value<N>
Number
You can invoke a generic type with any class, but you cannot invoke a generic type with a primitive type, such as
int
.Generics and Relationships Between Types
You might expect thatArrayList<Object>
is a supertype ofArrayList<String>
, becauseObject
is a supertype ofString
. In fact, no such relationship exists for instances of generic types. For example, consider the following code snippet:You might think that sinceList<String> ss = new ArrayList<String>(1); List<Object> os = ss; //WRONG. This causes a compile error.String
is a subclass ofObject
that assigningss
toos
shouldn't be a problem.But suppose that the above assignment was allowed and you then added an object to
os
:If you later tried to retrieve the object fromos.add(new Object());ss
:thess.get(0);Object
that is returned isn't guaranteed to be aString
this clearly violates howss
was defined. The compiler does not allow you to make any assignment that may compromise type safety.Generics and Type Erasure
Although the previous section says that the compiler doesn't allow you to make any assignment that may compromise type safety, there is one important exception to know about.
When a generic type is instantiated, the compiler translates those types by a technique called type erasure a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure means that Java applications that use generics maintain binary compatibility with Java libraries and applications created before generics.
For instance,
Iterator<String>
is translated to typeIterator
, which is called the raw type a raw type is a class without a type argument. This means that you can't find out what type ofObject
a generic class is using at runtime. The following operations are not possible:The operations shown in red are meaningless at runtime because the compiler removes all information about the actual type argument (represented by the type param E) at compile-time.public class MyClass<E> { public static void myMethod(Object item) { if (item instanceof E) { //Compiler error ... } E item2 = new E(); //Compiler error E iArray[] = new E[10]; //Compiler error E obj = (E)new Object(); //Unchecked cast warning } }Type erasure exists so that new code may continue to interface with legacy code, but it should not otherwise be considered good programming practice.
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.