泛型是在jdk1.5出现的, generic;为什么要使用泛型,对于这个问题,先看一个场景。
对于这样的操作,编译的时候,是不会报错的,在执行的时候,会报错的。
声明泛型
class Point<T>{ // 此处可以随便写标识符号,T是type的简称 private T var ; // var的类型由T指定,即:由外部指定 public T getVar(){ // 返回值的类型由外部决定 return var ; } public void setVar(T var){ // 设置的类型也由外部决定 this.var = var ; } };此时泛型T是String类型,由外部使用的时候指定的,
class Point<T>{ // 此处可以随便写标识符号,T是type的简称 private T var ; // var的类型由T指定,即:由外部指定 public T getVar(){ // 返回值的类型由外部决定 return var ; } public void setVar(T var){ // 设置的类型也由外部决定 this.var = var ; } }; public class GenericsDemo06{ public static void main(String args[]){ Point<String> p = new Point<String>() ; // 里面的var类型为String类型 p.setVar("MLDN") ; // 设置字符串 System.out.println(p.getVar().length()) ; // 取得字符串的长度 } };如果泛型是integer,但是设置内容给一个String,肯定会报错的 现在此处这个泛型T,相当于Integer,可以用它来替换,
class Point<T>{ // 此处可以随便写标识符号,T是type的简称 private T var ; // var的类型由T指定,即:由外部指定 public T getVar(){ // 返回值的类型由外部决定 return var ; } public void setVar(T var){ // 设置的类型也由外部决定 this.var = var ; } }; public class GenericsDemo07{ public static void main(String args[]){ Point<Integer> p = new Point<Integer>() ; // 里面的var类型为String类型 p.setVar("MLDN") ; // 设置字符串 } };对与之前的,数据类型不统一导致的问题,这里就可以通过泛型来进行验证
class Point<T>{ private T x ; // 表示X坐标 private T y ; // 表示Y坐标 public void setX(T x){ this.x = x ; } public void setY(T y){ this.y = y ; } public T getX(){ return this.x ; } public T getY(){ return this.y ; } }; public class GenericsPoint{ public static void main(String args[]){ Point<Integer> p = new Point<Integer>() ; p.setX(10) ; // 利用自动装箱操作:int --> Integer p.setY("北纬210度") ; // 利用自动装箱操作:int --> Integer int x = p.getX() ; // 自动拆箱 int y = p.getY() ; // 自动拆箱 System.out.println("整数表示,X坐标为:" + x) ; System.out.println("整数表示,Y坐标为:" + y) ; } };和使用Object方式的相比,省去了类型的强转,而且在编译器的时候就进行验证了数据类型,如果不是泛型要求的数据类型,则在程序编译的时候就会出现错误,可以保证数据类型的安全性。
构造方法可以为类中的属性初始化,那么如果类中的属性通过泛型指定,而又需要通过构造设置属性内容的时候,那么构造方法的定义与以前并无不同,不需要像声明类那样指定泛型。
class Point<T>{ // 此处可以随便写标识符号,T是type的简称 private T var ; // var的类型由T指定,即:由外部指定 public Point(T var){ // 通过构造方法设置内容 this.var = var ; } public T getVar(){ // 返回值的类型由外部决定 return var ; } public void setVar(T var){ // 设置的类型也由外部决定 this.var = var ; } }; public class GenericsDemo08{ public static void main(String args[]){ Point<String> p = new Point<String>("MLDN") ; // 里面的var类型为String类型 System.out.println("内容:" + p.getVar()) ; } };在泛型应用中,最好在声明类的对象的时候指定好其内部的数据类型。比如:Info info=null;
使用中没有指定泛型会如何呢?
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 GenericsDemo10{ public static void main(String args[]){ Info i = new Info() ; // 警告,没有指定泛型类型 i.setVar("MLDN") ; // 设置字符串 System.out.println("内容:" + i.getVar()) ; } };此时只是在编译期间产生了警告,但是程序依然可以执行。
在Java中为了保证程序依然可以使用,会将T设置成Object类型,这样一来,就可以接收任意的数据类型。也就是说,var的类型就是Object,所有的泛型信息将会被擦除,以上的程序就相当于下面的程序:
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 GenericsDemo11{ public static void main(String args[]){ Info<Object> i = new Info<Object>() ; // 指定Object为泛型类型 i.setVar("MLDN") ; // 设置字符串 System.out.println("内容:" + i.getVar()) ; } };这样的话,就是没有警告的,因为声明了泛型,虽然是object,但是也是声明的时候指定了。所以不会有警告。
在泛型的引用中,最好在声明类的时候指定好其内部的数据类型,例如Info,但是也可以不指定类型,这样一来用户在使用这样的类时,就会出现不安全的警告信息。
1,泛型产生,是为了保证数据类型的安全性。 2,泛型的使用,是由外部指定具体的操作类型。