Genericsの概要
Consider the following classes (written before the introduction of generics in JDK 5.0), designed to describe various kinds of media that a library might contain:
This is the primary reason that generic types and methods (often referred to, simply, as generics) were added to the Java language — to add compile-time type checking so the compiler can detect mismatched types at compile time, rather than runtime, when an exception is thrown.
Here is the same
generic type with a single
type parameter
type argument for each of its type parameters. A
Later on our imaginary program includes the following line of code:
You can further refine the declaration of
If you use any of the Java programming libraries that deal with groups of data, such as classes or interfaces that deal with collections, lists, arrays, and vectors, you will notice that they make extensive use of generics.
Note: When compiling code that refers to generics, you might encounter a message like this:
As mentioned in the text of the sample error, using the
This covers a simple case of using a generic class. Subsequent sections go into generic types in more detail and touch on generic methods.
public class Library { private List resources = new ArrayList(); public void addMedia(Media x) { resources.add(x); } public Media retrieveLast() { int size = resources.size(); if (size > 0) { return resources.get(size - 1); } return null; }}public class Media {}public class Book extends Media {}public class Video extends Media {}public class Newspaper extends Media {}
Given the above classes, imagine a program that uses them to catalog information about a collection of books (and only books). Here is a code snippet from that program: //A Library containing only BooksLibrary myBooks = new Library();...Book lastBook = (Book)myBooks retrieveLast();
Type casting the return value from the retrieveLast
method to Book
is necessary, so the compiler knows what kind of object is returned and what kinds of operations can be performed on that object. Even though the programmer may be certain that only Book
objects will be returned, the compiler does not know this. If a programming error did result in, say, a Video
being stored in myBooks
and then returned here, the cast would cause an unexpected exception to be thrown at runtime. This is the primary reason that generic types and methods (often referred to, simply, as generics) were added to the Java language — to add compile-time type checking so the compiler can detect mismatched types at compile time, rather than runtime, when an exception is thrown.
Here is the same
Library
class with a few simple changes (shown in bold), modified to use generics: public class Library<E> { private List resources = new ArrayList<E>(); public void addMedia(E x) { resources.add(x); } public E retrieveLast() { int size = resources.size(); if (size > 0) { return resources.get(size - 1); } return null; }}//The Media classes require no changes to use generics —//please refer to the original example.
Library is now a generic type with a single
type parameter
E
. When using a generic type, specify a type argument for each of its type parameters. A
Library
containing only Book
objects, for example, would be written as Library<Book>
. This is an example of a parameterized type
. The code snippet now looks like this: Library<Book> myBooks = new Library<Book>();...Book lastBook = myBooks retrieveLast();
The type cast and the comment are no longer needed because the Library
instance has been constrained to deal with Book
objects. The compiler now understands that this particular instance of Library
contains Book
s. If the compiler detects that the Library
is being used inappropriately — trying to add or retrieve a Newspaper
, for example — it generates an error. Later on our imaginary program includes the following line of code:
myBooks.addMedia(myFavoriteBook);
Without generics, the compiler couldn't warn you if myFavoriteBook
is of the wrong type. If it is a String
, for example, a runtime exception would occur somewhere down the road after someone invokes retrieveLast
. These sorts of errors can be especially hard to debug, since the runtime error may occur at a point in the code far removed from the actual programming error that caused it. With generics, the compiler calls out the error right away. You find out about the programming error immediately, and are shown exactly where the problem lies. You can further refine the declaration of
Library
to use Library<E extends Media>
. The compiler will enforce the constraint that a Library
can only contain Media
objects (and not, say, Number
s). If you use any of the Java programming libraries that deal with groups of data, such as classes or interfaces that deal with collections, lists, arrays, and vectors, you will notice that they make extensive use of generics.
Note: When compiling code that refers to generics, you might encounter a message like this:
Note: MyFile.java uses unchecked or unsafe operations.Note: Recompile with -Xlint:unchecked for details.
This error means that you have bypassed generics and have lost the benefit of compile-time type checking. You should fix your code to make full use of generics and take advantage of compile-time type checking. As mentioned in the text of the sample error, using the
-Xlink:unchecked
javac
option gives you the most information available about unchecked or type unsafe operations. This covers a simple case of using a generic class. Subsequent sections go into generic types in more detail and touch on generic methods.