1. Generics 泛型引入
泛型是在Java 5 之后引入到java 语言中的,其目的是为了提供编译时类型检查,减少ClassCastException异常风险。容器参数化能力是当初Generic引入的一个主要动力,它将运行时异常ClassCastException在编译时就强制检查,如果类型不匹配将抛出一个编译时错误。
2. Generic Class泛型类
我们可以定义泛型类。泛型类型是一种具有参数化类型的类或接口,我们使用(<>)来指定这种类型参数。
package com.fqy.generic;
public class GenericClass<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
GenericClass<Integer> intClass = new GenericClass<>();
GenericClass<String> strClass = new GenericClass<>();
intClass.add(10);
strClass.add("Hello sdy");
System.out.println("Integer value: " + intClass.get());
System.out.println("String value: " + strClass.get());
}
}
//Running result:
Integer value: 10
String value: Hello sdy
3. 泛型方法Generic Method
有时,我们并不想参数化整个类,这时,我们可以选择创建泛型方法。因为构造函数是一种特殊的方法,所以我们可以在构造函数中使用泛型。
package com.fqy.generic;
public class GeMethod {
// Determine the largest of three Comparable objects
public static <T extends Comparable<T>> T maxInThree(T x, T y, T z) {
T max = x;
if (y.compareTo(max) > 0)
max = y;
if (z.compareTo(max) > 0)
max = z;
return max;
}
public static void main(String[] args) {
System.out.printf("Max of %d %d %d is %d\n", 3, 4, 5, maxInThree(3, 4, 5));
System.out.printf("Max of %.1f %.1f %.1f is %.1f\n", 8.9, 4.7, 5.6, maxInThree(8.9, 4.7, 5.6));
System.out.printf("Max of %s %s %s is %s\n", "pear", "apple", "banana", maxInThree("pear", "apple", "banana"));
}
}
//Running result:
Max of 3 4 5 is 5
Max of 8.9 4.7 5.6 is 8.9
Max of pear apple banana is pear
4. 有限制的类型参数
- 泛型通配符:’?’是泛型通配符,并代表了一种未知的类型。该通配符可以用作参数、数据域、局部变量的类型,有时被用于返回值。在我们调用泛型方法或实例化一个泛型类时,我们不能使用通配符。
- 泛型上界通配符:上界通配符是用来松弛方法中变量类型的限制。
//A method to return the sum of a list
public double sum(List<Number> list){
double sum = 0;
for(Number n: list)
sum += n.doubleValue();
return sum;
}
//上述代码问题时,对于List<Integer> & List<Double>上述方法就不适用了,这个时候就需要上界通配符了。
public double sum(List<? extends Number> list){
double sum = 0;
for(Number n: list)
sum += n.doubleValue();
return sum;
}
- 泛型无界通配符: 有时,我们希望我们的泛型方法适用于所有的类型,这时无界的通配符就可以使用了, 和使用
public void printData(List<?> list){
for(Object obj: list)
System.out.println(obj+" ");
}
- 泛型下界通配符:假设我们想要添加整形数据到一个整形的list中,我们可以设置参数为 List,但是这将限制了一些类型,因为List和 List也可能有整形数据,这时我们就可以用下界通配符达到这个目的了。
public void addIntegers<List<? super Integer> list){
list.add(new Integer<50>);
}
5. Java泛型类型擦除机制
java中的泛型引入只是为了提供一种编译时类型检测机制,其在运行时没有任何作用;所以java编译器使用类型擦除机制来移除所有的类型检测代码,并在必要时候插入类型转换。类型擦除保证了没有为参数化类型创建新类;相应的,泛型不会招致人和运行时开销。
另:
//Error: generic doesn't support sub-typing
List<Number> numbers = new ArrayList<Integer>();
//Error: we can't create generic array.
List<Integer>[] array = new ArrayList<Integer>[10];