Java 简明教程
Java - Generics
如果能够编写一个单一的 sort 方法对 Integer 数组、String 数组或支持排序的任何类型的数组中的元素进行排序,那就太好了。
It would be nice if we could write a single sort method that could sort the elements in an Integer array, a String array, or an array of any type that supports ordering.
Why Generics are used in Java?
通用类型用于创建具有可仅针对 different data types 进行运算的参数的诸如此类的 classes 、 interfaces 和 methods 。此功能在 Java 5 中引入。
Generics are used to create such classes, interfaces, and methods with parameters that can operate on different data types along. This feature was introduced in Java 5.
Java - Generics
Java Generic 方法和泛型类使程序员能够通过单个方法声明指定一组相关方法,或通过单个类声明指定一组相关类型。
Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively.
泛型还提供编译时类型安全性,使程序员能够在编译时捕捉无效的类型。
Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.
使用 Java 泛型概念,我们可以为对象数组编写一个泛型方法,然后使用 Integer 数组、Double 数组、String 数组等调用泛型方法,对数组元素进行排序。
Using Java Generic concept, we might write a generic method for sorting an array of objects, then invoke the generic method with Integer arrays, Double arrays, String arrays and so on, to sort the array elements.
Advantage of Java Generics
-
No scarification of type-safety
-
No requirement of type-casting
-
Compile-time checking
-
Code reusability and improved performance
Types of Java Generics
Generic Methods
您可以编写一个单一的泛型方法声明,该声明可以用不同类型的参数进行调用。根据传递给泛型方法的参数的类型,编译器会适当地处理每个方法调用。
You can write a single generic method declaration that can be called with arguments of different types. Based on the types of the arguments passed to the generic method, the compiler handles each method call appropriately.
以下是定义泛型方法的规则:
Following are the rules to define Generic Methods −
-
All generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the method’s return type ( < E > in the next example).
-
Each type parameter section contains one or more type parameters separated by commas. A type parameter, also known as a type variable, is an identifier that specifies a generic type name.
-
The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.
-
A generic method’s body is declared like that of any other method. Note that type parameters can represent only reference types, not primitive types (like int, double and char).
以下示例说明了如何使用单个泛型方法打印不同类型的数组 -
Following example illustrates how we can print an array of different type using a single Generic method −
public class GenericMethodTest {
// generic method printArray
public static < E > void printArray( E[] inputArray ) {
// Display array elements
for(E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String args[]) {
// Create arrays of Integer, Double and Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("Array integerArray contains:");
printArray(intArray); // pass an Integer array
System.out.println("\nArray doubleArray contains:");
printArray(doubleArray); // pass a Double array
System.out.println("\nArray characterArray contains:");
printArray(charArray); // pass a Character array
}
}
Output
Array integerArray contains:
1 2 3 4 5
Array doubleArray contains:
1.1 2.2 3.3 4.4
Array characterArray contains:
H E L L O
Bounded Type Parameters
有时您可能希望限制允许传递给类型参数的类型种类。例如,对数字进行操作的方法可能只希望接受 Number 或其子类的实例。这就是有界类型参数的作用。
There may be times when you’ll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
要声明有界类型参数,请列出类型参数的名称,后跟 extends 关键字,后跟其上限。
To declare a bounded type parameter, list the type parameter’s name, followed by the extends keyword, followed by its upper bound.
以下示例说明了如何以常规意义使用 extends 表示“extends”(如在类中)或“implements”(如在接口中)。此示例是用于返回三个 Comparable 对象中最大的对象的泛型方法 -
Following example illustrates how extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces). This example is Generic method to return the largest of three Comparable objects −
public class MaximumTest {
// determines the largest of three Comparable objects
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // assume x is initially the largest
if(y.compareTo(max) > 0) {
max = y; // y is the largest so far
}
if(z.compareTo(max) > 0) {
max = z; // z is the largest now
}
return max; // returns the largest object
}
public static void main(String args[]) {
System.out.printf("Max of %d, %d and %d is %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ));
System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ));
System.out.printf("Max of %s, %s and %s is %s\n","pear",
"apple", "orange", maximum("pear", "apple", "orange"));
}
}
Output
Max of 3, 4 and 5 is 5
Max of 6.6,8.8 and 7.7 is 8.8
Max of pear, apple and orange is pear
Generic Classes
泛型类声明看起来像非泛型类声明,除了类名后跟类型参数部分。
A generic class declaration looks like a non-generic class declaration, except that the class name is followed by a type parameter section.
与泛型方法一样,泛型类的类型参数部分可以有多个类型参数,用逗号分隔。这些类被称为参数化类或参数化类型,因为它们接受一个或多个参数。
As with generic methods, the type parameter section of a generic class can have one or more type parameters separated by commas. These classes are known as parameterized classes or parameterized types because they accept one or more parameters.
以下示例说明了如何定义泛型类 -
Following example illustrates how we can define a generic class −
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}
}
Output
Integer Value :10
String Value :Hello World