Java从1.5以后支持泛型,泛型的本质是参数化类型,也就是说所操做的数据类型被指定为一个参数。这种参数类型能够用在类、接口和方法的建立中,分别称为泛型类、泛型接口、泛型方法。javascript
入不支持泛型,则表现为支持Object,不是特定的泛型。css
泛型是对 Java 语言的类型系统的一种扩展,以支持建立能够按类型进行参数化的类。能够把类型参数看做是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符同样。java
能够在集合框架中看到泛型的动机。例如,List类容许您向一个 List添加任意类的对象,即便最多见的状况List.add()。
由于 list.get() 被定义为返回 Object,因此通常必须将 list.get() 的结果强制类型转换为指望的类型,以下面的代码所示:
List list = new ArrayList();
list .add("obj");
String s = (String) list.get(0);
要让程序经过编译,必须将 get() 的结果强制类型转换为 String,而且但愿结果然的是一个 String。可是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。
理想状况下,您可能会得出这样一个观点,即 list 是一个 List,它将 String 键映射到 String 值。android
泛型能够消除代码中的强制类型转换,同时得到一个附加的类型检查层,该检查层能够防止有人将错误类型的键或值保存在集合中。这就是泛型所作的工做。程序员
泛型的好处数组
Java 语言中引入泛型是一个较大的功能加强。不只语言、类型系统和编译器有了较大的变化,以支持泛型,并且类库也进行了大翻修,因此许多重要的类,好比集合框架,都已经成为泛型化的了。安全
这带来了不少好处:
1,类型安全。 泛型的主要目标是提升 Java 程序的类型安全。经过知道使用泛型定义的变量的类型限制,编译器能够在一个高得多的程度上验证类型假设。ruby
没有泛型,这些假设就只存在于程序员的头脑中(或者若是幸运的话,还存在于代码注释中)。 框架
2,消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,而且减小了出错机会。性能
3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。
可是更多类型信息可用于编译器这一事实,为将来版本的 JVM 的优化带来可能。因为泛型的实现方式,支持泛型(几乎)不须要 JVM 或类文件更改。
全部工做都在编译器中完成,编译器生成相似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。
Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,而且全部的强制转换都是自动和隐式的,提升代码的重用率。
泛型在使用中还有一些规则和限制:
一、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
二、同一种泛型能够对应多个版本(由于参数类型是不肯定的),不一样版本的泛型类实例是不兼容的。
三、泛型的类型参数能够有多个。
四、泛型的参数类型可使用extends语句,例如<T extends superclass>。习惯上成为“有界类型”。
五、泛型的参数类型还能够是通配符类型。例如Class<?> classType = Class.forName(Java.lang.String);
泛 型还有接口、方法等等,内容不少,须要花费一番功夫才能理解掌握并熟练应用。在此给出我曾经了解泛型时候写出的两个例子(根据看的印象写的),实现一样的 功能,一个使用了泛型,一个没有使用,经过对比,能够很快学会泛型的应用,学会这个基本上学会了泛型70%的内容。
泛型的使用场景
在开发中对象的引用传递是最多见的,可是在泛型操做中,进行引用传递的时候泛型必须匹配才能够传递,不然没法传递。
class Info<T>{
private T var ; // 定义泛型变量
public void setVar(T var){
this.var = var ;
}
public T getVar(){
return this.var ;
}
public String toString(){
// 直接打印
return this.var.toString() ;
} };
public class GenericsDemo14{
public static void main(String args[]){ Info<String> i = new Info<String>() ; // 使用String为泛型类型 i.setVar("MLDN") ; // 设置内容 fun(i) ; } public static void fun(Info<?> temp){ // 能够接收任意的泛型对象 System.out.println("内容:" + temp) ; } };
使用?能够接受任意类型的数据,却没法进行修改,?w为通配符。
class Info<T> { private T var; // 定义泛型变量 public T getVar() { return var; } public void setVar(T var) { this.var = var; } public String toString(){ // 直接打印 return var.toString(); } } public class GenericsDemo17 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Info<Integer> info1 = new Info<Integer>(); // 声明Integer的泛型对象 Info<Float> info2 = new Info<Float>(); // 声明Float的泛型对象 Info<String> info3 = new Info<String>(); info1.setVar(30); // 设置整数,自动装箱 info2.setVar(30.1F); // 设置小数,自动装箱 info3.setVar("俺是字符串,不能被受限的FUN组装"); fun(info1); fun(info2); // fun(info3); //受限了,不能调用这个 } /** * 能够接收任意的泛型对象(// 只能接收Number及其Number的子类) * @param temp */ public static void fun(Info<? extends Number> temp){ // 只能接收String或Object类型的泛型 //public static void fun(Info<? super String> temp){ System.out.println("内容:"+temp); } }
不只仅在使用过程当中,也能够在定义类的时候指定泛型上限:
class Info<T extends Number>{ // 此处泛型只能是数字类型 private T var ; // 定义泛型变量 public void setVar(T var){ this.var = var ; } public T getVar(){ return this.var ; } public String toString(){ // 直接打印 return this.var.toString() ; } }; public class GenericsDemo19{ public static void main(String args[]){ Info<Integer> i1 = new Info<Integer>() ; // 声明Integer的泛型对象 } };
若是设置成Stirng类型就会出现错误:
GenericsDemo20.java:15: 类型参数 java.lang.String 不在其限制范围以内 Info<String> i1 = new Info<String>() ; // 声明Integer的 泛型对象
String 不是Number的子类,最高不能超过Number的子类。
泛型适用于本类以及父类类型上的时候,必须使用泛型下限。
以下只能接受String以及String的父类。最低不能接受Stirng类及其父类之外的类。
class Info<T>{ private T var ; // 定义泛型变量 public void setVar(T var){ this.var = var ; } public T getVar(){ return this.var ; } public String toString(){ // 直接打印 return this.var.toString() ; } }; public class GenericsDemo21{ public static void main(String args[]){ Info<String> i1 = new Info<String>() ; // 声明String的泛型对象 Info<Object> i2 = new Info<Object>() ; // 声明Object的泛型对象 i1.setVar("hello") ; i2.setVar(new Object()) ; fun(i1) ; fun(i2) ; } public static void fun(Info<? super String> temp){ // 只能接收String或Object类型的泛型 System.out.print(temp + "、") ; } };
注意:子类没法使用父类的泛型类型进行接受。
class Info<T>{ private T var ; // 定义泛型变量 public void setVar(T var){ this.var = var ; } public T getVar(){ return this.var ; } public String toString(){ // 直接打印 return this.var.toString() ; } }; public class GenericsDemo23{ public static void main(String args[]){ Info<String> i1 = new Info<String>() ; // 泛型类型为String Info<Object> i2 = null ; i2 = i1 ; } };
就会爆以下错误:
GenericsDemo23.java:17: 不兼容的类型 找到: Info<java.lang.String> 须要: Info<java.lang.Object> i2 = i1 ; ^
在jdk1.5之后,不只仅能够声明泛型类,也能够声明泛型接口,泛型接口很相似泛型类:
访问权限 +interface +接口名称 + <泛型标示>{}
1:
interface Info<T>{ // 在接口上定义泛型 public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型 } class InfoImpl implements Info<String>{ // 定义泛型接口的子类 private String var ; // 定义属性 public InfoImpl(String var){ // 经过构造方法设置属性内容 this.setVar(var) ; } public void setVar(String var){ this.var = var ; } public String getVar(){ return this.var ; } }; public class GenericsDemo{ public static void main(String arsg[]){ Info i = null; // 声明接口对象 i = new InfoImpl("soyoungboy") ; // 经过子类实例化对象 System.out.println("内容:" + i.getVar()) ; } };
2:
interface Info<T>{ // 在接口上定义泛型 public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型 } class InfoImpl<T> implements Info<T>{ // 定义泛型接口的子类 private T var ; // 定义属性 public InfoImpl(T var){ // 经过构造方法设置属性内容 this.setVar(var) ; } public void setVar(T var){ this.var = var ; } public T getVar(){ return this.var ; } }; public class GenericsDemo{ public static void main(String arsg[]){ Info<String> i = null; // 声明接口对象 i = new InfoImpl<String>("soyoungboy") ; // 经过子类实例化对象 System.out.println("内容:" + i.getVar()) ; } };
泛型方法定义:
访问权限 +<泛型标示>+泛型标示 方法名称(泛型标示 参数名称)
class Demo{ public <T> T fun(T t){ // 能够接收任意类型的数据 return t ; // 直接把参数返回 } }; public class GenericsDemo{ public static void main(String args[]){ Demo d = new Demo() ; // 实例化Demo对象 String str = d.fun("soyoungboy") ; // 传递字符串 int i = d.fun(30) ; // 传递数字,自动装箱 System.out.println(str) ; // 输出内容 System.out.println(i) ; // 输出内容 } };
class Info<T extends Number>{ // 指定上限,只能是数字类型 private T var ; // 此类型由外部决定 public T getVar(){ return this.var ; } public void setVar(T var){ this.var = var ; } public String toString(){ // 覆写Object类中的toString()方法 return this.var.toString() ; } }; public class GenericsDemo27{ public static void main(String args[]){ Info<Integer> i = fun(30) ; System.out.println(i.getVar()) ; } public static <T extends Number> Info<T> fun(T param){ Info<T> temp = new Info<T>() ; // 根据传入的数据类型实例化Info temp.setVar(param) ; // 将传递的内容设置到Info对象的var属性之中 return temp ; // 返回实例化对象 } };
class Info<T>{ // 指定上限,只能是数字类型 private T var ; // 此类型由外部决定 public T getVar(){ return this.var ; } public void setVar(T var){ this.var = var ; } public String toString(){ // 覆写Object类中的toString()方法 return this.var.toString() ; } }; public class GenericsDemo{ public static void main(String args[]){ Info<Integer> i1 = new Info<Integer>() ; Info<String> i2 = new Info<String>() ; i1.setVar(30) ; // 设置内容 i2.setVar("aoyoungboy") ; // 设置内容 add(i1,i2) ; } public static <T> void add(Info<T> i1,Info<T> i2){ System.out.println(i1.getVar() + " " + i2.getVar()) ; } };
就会产生错误:
泛型】_泛型的其余应用\代码>javac GenericsDemo.java GenericsDemo29.java:19: 没法将 GenericsDemo 中的 <T>add(Info<T>,Info<T>) 应用 于 (Info<java.lang.Integer>,Info<java.lang.String>) add(i1,i2) ; ^
使用泛型方法的时候,也能够传递或者返回一个泛型数组:
public class GenericsDemo{ public static void main(String args[]){ Integer i[] = fun1(1,2,3,4,5,6) ; // 返回泛型数组 fun2(i) ; } public static <T> T[] fun1(T...arg){ // 接收可变参数 return arg ; // 返回泛型数组 } public static <T> void fun2(T param[]){ // 输出 System.out.print("接收泛型数组:") ; for(T t:param){ System.out.print(t + "、") ; } } };
class Info<T,V>{ // 接收两个泛型类型 private T var ; private V value ; public Info(T var,V value){ this.setVar(var) ; this.setValue(value) ; } public void setVar(T var){ this.var = var ; } public void setValue(V value){ this.value = value ; } public T getVar(){ return this.var ; } public V getValue(){ return this.value ; } }; class Demo<S>{ private S info ; public Demo(S info){ this.setInfo(info) ; } public void setInfo(S info){ this.info = info ; } public S getInfo(){ return this.info ; } }; public class GenericsDemo{ public static void main(String args[]){ Demo<Info<String,Integer>> d = null ; // 将Info做为Demo的泛型类型 Info<String,Integer> i = null ; // Info指定两个泛型类型 i = new Info<String,Integer>("李兴华",30) ; // 实例化Info对象 d = new Demo<Info<String,Integer>>(i) ; // 在Demo类中设置Info类的对象 System.out.println("内容一:" + d.getInfo().getVar()) ; System.out.println("内容二:" + d.getInfo().getValue()) ; } };