Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ganesh_JavaSE7_Programming_1z0-804_study_guide.pdf
Скачиваний:
94
Добавлен:
02.02.2015
Размер:
5.88 Mб
Скачать

Chapter 6 GeneriCs and ColleCtions

In the collections part of this chapter, you’ll learn how to use the readily available data structures (implemented using generics) provided as part of the Java library. We’ll discuss some interfaces and concrete classes in the collections framework that are important from the OPCJP 7 exam perspective.

Generics

Generics are a language feature introduced to Java in Version 1.5. Generics help you write code for one type (say T) that is applicable for all types, instead of writing separate classes for each type. Before generics were introduced in Java, the Object base class was used as an alternative to generics. However, using the Object class for storing elements in

a container results in type safety issues—that is, using such a container allows type errors that cannot be identified by the Java compiler and result in runtime exceptions. If you don’t understand this description of type safety, don’t worry because we’re going to explain the type safety problem in detail with a few examples. Understanding type safety is important. In fact, the main motivation for adding generics to the language was because legacy container classes were not type-safe.

Using Object Type and Type Safety

Before the introduction of generics in Java, data structures were implemented by storing and processing elements using the Object base class. We’ll discuss an example to understand why those containers are not type-safe. Consider the program in Listing 6-1, which uses the Vector class (you can think of Vector as a “dynamically growing array” where you can add or remove elements similar to an array). Can you predict the output of this program?

Listing 6-1. OldContainerTest.java

import java.util.Vector;

// This program demonstrate the lack of type-safety in containers (based on Object type). class OldContainerTest {

public static void main(String []args) { Vector floatValues = new Vector(); floatValues.add(10.0f); floatValues.add(100.0);

for(int i = 0; i < floatValues.size(); i++) { System.out.println(floatValues.get(i));

}

}

}

It prints the following:

10.0

100.0

Now let’s make only one change to this program: instead of directly printing the values returned from Vector's get method, you first store it in a temporary variable of Float type and then print that temporary value using println:

Float temp = (Float) floatValues.get(i);

System.out.println(temp);

148

Chapter 6 Generics and Collections

Now this is the output:

10.0

Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float at OldContainerTest.main(OldContainerTest.java:9)

Why? What happened? The Vector container is capable of holding any object (i.e., it holds values of the Object type). When you try to put a primitive type, however, it is “boxed” automatically and the wrapper object is put into the container (using the autoboxing feature in Java). For 10.0, the corresponding primitive type is float

(note the suffix “f”!), and so a wrapper object of type Float is created and that object is put into the Vector. For 100.0, the primitive type is Double (real numbers, if not given with explicit suffix, are assumed of type Double by default). So, the wrapper object of type Double is created and that object is put into the Vector.

So far, so good. In the original program, there were no casts, so the floating point values were directly printed using the toString() method in println. However, when you try to cast it using the Float type, you get into trouble. You cannot convert the Double value 100.0 into Float type. (Float type can be casted to Double type—but Float type cannot be casted to Double type!) So you get a ClassCastException at runtime.

In other words, a Vector is implemented in terms of Object type. So, you can put an object of any type into a Vector object. You cannot enforce that only elements of certain type can be inserted to the container at compile time. In fact, while compiling the program, the compiler does warn you about using raw type Vector (see Figure 6-1). We’ll discuss more about these raw types (i.e., non-generic types) in the “Interoperability of Raw Types and Generic Types” section of this chapter.

Figure 6-1.  Compiler warning about the use of raw type Vector

The Vector container that uses the Object base class for storing elements allows you to add elements of any type, while your application logic requires that only strings should be added. With generics, you can specify to the compiler that only elements of a certain type can be added to a container. Generics will ensure that any attempts to add elements of types other than the specified type(s) will be caught at compile time itself. In other words, the use of data structures implemented using generics is checked for type safety at compile time, so those data structures are type-safe.

149

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]