java泛型

认识泛型

泛型可以解决数据类型转换之中的安全问题,它的主要原理就是,在类的声明的时候,通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或者实例化的时候只要指定好需要的类型即可。
在类型转换的例子中,我们由过自动拆箱和自动装箱的机制,
只需要将我们的类声明为Object即可。
型的定义:泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数,在用到的时候在指定具体的类型。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。
泛型思想早在C++语言的模板(Templates)中就开始生根发芽,在Java语言处于还没有出现泛型的版本时,只能通过Object是所有类型的父类和类型强制转换两个特点的配合来实现类型泛化。例如在哈希表的存取中,JDK 1.5之前使用HashMap的get()方法,返回值就是一个Object对象,由于Java语言里面所有的类型都继承于java.lang.Object,那Object转型为任何对象成都是有可能的。但是也因为有无限的可能性,就只有程序员和运行期的虚拟机才知道这个Object到底是个什么类型的对象。在编译期间,编译器无法检查这个Object的强制转型是否成功,如果仅仅依赖程序员去保障这项操作的正确性,许多ClassCastException的风险就会被转嫁到程序运行期之中。
泛型技术在C#和Java之中的使用方式看似相同,但实现上却有着根本性的分歧,C#里面泛型无论在程序源码中、编译后的IL中(Intermediate Language,中间语言,这时候泛型是一个占位符)或是运行期的CLR中都是切实存在的,List与List就是两个不同的类型,它们在系统运行期生成,有自己的虚方法表和类型数据,这种实现称为类型膨胀,基于这种方法实现的泛型被称为真实泛型。
Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经被替换为原来的原始类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此对于运行期的Java语言来说,ArrayList与ArrayList就是同一个类。所以说泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型。(类型擦除在后面在学习)
使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。泛型对于集合类来说尤其有用。
泛型程序设计(Generic Programming)意味着编写的代码可以被很多不同类型的对象所重用。

泛型的构造

泛型的使用需要遵循的规律如下:

  1. 泛型类的使用:一个泛型类(generic class)就是具有一个或多个类型变量的类。定义一个泛型类十分简单,只需要在类名后面加上<>,再在里面加上类型参数:

    class Pair {
    private T value;
    public Pair(T value) {
    this.value=value;
    }
    public T getValue() {
    return value;
    }
    public void setValue(T value) {
    this.value = value;
    }
    }

  2. 泛型接口的定义和使用
    定义泛型接口和泛型类差不多,看下面简单的例子:

interface Show<T,U>{  
void show(T t,U u);  
}  

class ShowTest implements Show<String,Date>{  
@Override  
public void show(String str,Date date) {  
System.out.println(str);  
System.out.println(date);  
}  
}  
  1. 泛型方法的定义和使用
    泛型类在多个方法签名间实施类型约束。在 List 中,类型参数 V 出现在 get()、add()、contains() 等方法的签名中。当创建一个 Map 类型的变量时,您就在方法之间宣称一个类型约束。您传递给 add() 的值将与 get() 返回的值的类型相同。
    类似地,之所以声明泛型方法,一般是因为您想要在该方法的多个参数之间宣称一个类型约束。
    举个简单的例子:

    public static void main(String[] args) throws ClassNotFoundException {  
    String str=get("Hello", "World");  
    System.out.println(str);  
     }  
    
    public static <T, UT get(T t, U u) {  
    if (u != null)  
    return t;  
    else  
    return null;  
     }  
    

    总结

    泛型的使用是写了一个标识
    这样就是表示我们使用了泛型。
    在类和接口的声明里面是
    class name<T1,T2,T3....>{}
    在接口里面是

    `Interface name<T1,T2,T3...>{}`
    

    在方法里面是
    <T1,T2,T3> T1 name(T2 param1,T2 param2){}