Java泛型

1 什么是泛型


泛型即参数化类型,即是将类型由原本的类型参数化,类似于方法中的变量参数,此时类型也可以当作参数传入(可以称之为类型参数)。

2 为什么要使用泛型


先看一段代码:

List list = new ArrayList();  
list.add("Acey");  
list.add(100);  
for (int i = 0; i < list.size(); i++) {  
  String name = (String) list.get(i); //取出Integer时,运行时出现异常  
System.out.println("name:" + name);  
} 

当我们在list中插入一个字符串和整数时是合法的,因为list默认的泛型即为Object类型。但是当我们从集合中取出数据时,需要对不同的类型进行强转成符合的对应的类型。为了解决这一问题,泛型就出现了。

3 泛型的使用


  • Java泛型变成时在jdk1.5版本后引出的,使用的时候注意了。。
  • 泛型只在编译阶段有用,在编译的过程中,将会正确的检验泛型的结果,将泛型的相关信息擦除,在对象进入和离开方法的边界时会加上对应的类型转换方法。也就是说在成功编译成class文件后将不会在包含任何泛型的信息。

4 泛型方法


对于常见的泛型模式,推荐的名称:
K - 键
V - 值
E - 异常
T - 泛型

泛型方法使得该方法能独立于类而产生变化。以下是一个基本的指导原则:无论何时,只要你能做到,你就应该尽量使用泛型方法。也就是说,如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法,因为它可以使事情更清楚明白。另外,对于一个static的方法而言,无法访问泛型类的类型参数。所以,如果static方法需要使用泛型能力,就必须使其成为泛型方法。
要定义泛型方法,只需将泛型参数列表置于返回值之前,就像下面这样:

 public  void f(T x){  
        System.out.println(x.getClass().getName());  
    }  

可变参数与泛型方法
public static  List makeList(T... args){  
        List result = new ArrayList();  
        for(T item:args)  
            result.add(item);  
        return result;         
    }  

5 构建一个复杂的元组


元组和``list```列表一样,都是用来存储数据,但是和列表不同的是,列表只能存储相同的数据类型,而元组可以存储多种数据类型,且可以根据自己的需求无线扩展。

class ThreeTuple2{  
    public final A first;  
    public final B second;  
    private final C three;  
    public ThreeTuple2(A a,B b,C c){  
        first = a;  
        second = b;  
        three = c;  
    }  
    public String toString(){  
        return "(" + first + "," + second + "," + three + ")";  
    }  
} 

6 泛型通配符 “ ? ”


在不确定使用哪种类型的时候可以使用泛型通配符 “? ”来代替,但是在操作该类型的对象时,只能使用Object中的功能。

ClassclassType = Class.forName("java.lang.String");

7 泛型的上限和下限


上限:? extends E 可以接收 E 类型或E类型以下的类型对象
上限:? super E 可以接收E类型或E类型以上的类型对象。

7 泛型擦除

java 泛型是用泛型擦除来实现的,类型擦除就是说Java泛型只能用于在编译期间的静态类型检查,然后编译器生成的代码会擦除相应的类型信息,这样到了运行期间实际上JVM根本就知道泛型所代表的具体类型。这样做的目的是因为Java泛型是1.5之后才被引入的,为了保持向下的兼容性,所以只能做类型擦除来兼容以前的非泛型代码

public class Node {
    private T data;
    private Node next;
    public Node(T data, Node next) {
        this.data = data;
        this.next = next;
    }
    public T getData() { return data; }

}

编译器在做了相应的检查后,在运行期间上面的代码会转换为

public class Node {
    private Object data;
    private Node next;
    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }
    public Object getData() { return data; }
    // ...
}

这也就是说,我们若只是给定了泛型参数 T 的话,那么不管我们传进来的是 Integer 还是 String .... 最终都会被当作 Object 来看待。
如果我们想要设置自己的 bounds ,那么我们就应该使用上限来设置。

public class Node> {
    private T data;
    private Node next;
    public Node(T data, Node next) {
        this.data = data;
        this.next = next;
    }
    public T getData() { return data; }
    // ...
}

你可能感兴趣的:(Java泛型)