Java 泛型详解:T 和ClassT 的使⽤。泛型类,泛型⽅法的详细
使⽤实例
⼀、引⼊
1、泛型是什么
⾸先告诉⼤家ArrayList 就是泛型。那ArrayList 能完成哪些想不到的功能呢?先看看下⾯这段代码:
⼤家对ArrayList 很熟悉,这⾥构造了三个List,分别盛装String 、Integer 和Double ;这就是ArrayList 的过⼈之处:即各种类型的变量都可以组装成对应的List ,⽽不必针对每个类型分别实现⼀个构建ArrayList 的类。这⾥可能看不懂,开篇总是困难的,下⾯看看如果没有泛型的话,我们要怎么做;
2、没有泛型会怎样
先看下⾯这段代码:
我们实现两个能够设置点坐标的类,分别设置Integer 类型的点坐标和Float 类型的点坐标:
那现在有个问题:⼤家有没有发现,他们除了变量类型不⼀样,⼀个是Integer ⼀个是Float 以外,其它
并没有什么区别!那我们能不能合并成⼀个呢? 答案是可以的,因为Integer 和Float 都是派⽣⾃Object 的,我们⽤下⾯这段代码代替: [java]
01. ArrayList<String> strList = new  ArrayList<String>();  02. ArrayList<Integer> intList = new  ArrayList<Integer>();  03. ArrayList<Double> doubleList = new  ArrayList<Double>();  [java]
01. //设置Integer 类型的点坐标  02. class  IntegerPoint{  03.    private  Integer x ;      // 表⽰X 坐标  04.    private  Integer y ;      // 表⽰Y 坐标  05.    public  void  setX(Integer x){  06.        this .x = x ;  07.    }  08.    public  void  setY(Integer y){  09.        this .y = y ;  10.    }  11.    public  Integer getX(){  12.        return  this .x ;  13.    }  14.    public  Integer getY(){  15.        return  this .y ;  16.    }  17. }  18. //设置Float 类型的点坐标  19. class  FloatPoint{  20.    private  Float x ;      // 表⽰X 坐标  21.    private  Float y ;      // 表⽰Y 坐标  22.    public  void  setX(Float x){  23.        this .x = x ;  24.    }  25.    public  void  setY(Float y){  26.        this .y = y ;  27.    }  28.    public  Float getX(){  29.        return  this .x ;  30.    }  31.    public  Float getY(){  32.        return  this .y ;  33.    }  34. }
即全部都⽤Object 来代替所有的⼦类;
在使⽤的时候是这样的:
在设置的时候,使⽤new Integer(100)来新建⼀个Integer
然后在取值的时候,进⾏强制转换:
由于我们设置的时候,是设置的Integer ,所以在取值的时候,强制转换是不会出错的。
同理,FloatPoint 的设置和取值也是类似的,代码如下:
但问题来了:注意,注意,我们这⾥使⽤了强制转换,我们这⾥setX ()和getX ()写得很近,所以我们明确的知道我们传进去的是Float 类型,那如果我们记错了呢?
⽐如我们改成下⾯这样,编译时会报错吗:
不会我们问题的关键在于这句:
强制转换时,会不会出错。因为编译器也不知道你传进去的是什么,⽽X()返回的类型是Object ,所以编译时,将Object 强转成String 是成⽴的。必然不会报错。
⽽在运⾏时,则不然,在运⾏时,floatPoint 实例中明明传进去的是Float 类型的变量,⾮要把它强转成String 类型,肯定会报类型转换错误的!
那有没有⼀种办法在编译阶段,即能合并成同⼀个,⼜能在编译时检查出来传进去类型不对呢?当然,这就是泛型。
下⾯我们将对泛型的写法和⽤法做⼀⼀讲解。
⼆、各种泛型定义及使⽤
1、泛型类定义及使⽤
我们先看看泛型的类是怎么定义的: 01. class  ObjectPoint{  02.    private  Object x ;  03.    private  Object y ;  04.    public  void  setX(Object x){  05.        this .x = x ;  06.    }  07.    public  void  setY(Object y){  08.        this .y = y ;  09.    }  10.    public  Object getX(){  11.        return  this .x ;  12.    }  13.    public  Object getY(){  14.        return  this .y ;  15.    }  16. }
[java]
01. ObjectPoint integerPoint = new  ObjectPoint();  02. integerPoint.setX(new  Integer(100));  03. Integer integerX=(X();
[java]
01. integerPoint.setX(new  Integer(100));
[java]
01. Integer integerX=(X();
[java]
01. ObjectPoint floatPoint = new  ObjectPoint();  02. floatPoint.setX(new  Float(100.12f));  03. Float floatX = (X();
[java]
01. ObjectPoint floatPoint = new  ObjectPoint();  02. floatPoint.setX(new  Float(100.12f));  03. String floatX = (X();
[java]
01. String floatX = (X();
先看看运⾏结果:
从结果中可以看到,我们实现了开篇中IntegerPoint 类和FloatPoint 类的效果。下⾯来看看泛型是怎么定义及使⽤的吧。
(1)、定义泛型:Point<T>
⾸先,⼤家可以看到Point<T>,即在类名后⾯加⼀个尖括号,括号⾥是⼀个⼤写字母。这⾥写的是T ,其实这个字母可以是任何⼤写字母,⼤家这⾥先记着,可以是任何⼤写字母,意义是相同的。
(2)类中使⽤泛型
这个T 表⽰派⽣⾃Object 类的任何类,⽐如String,Integer,Double 等等。这⾥要注意的是,T ⼀定是派⽣于Object 类的。为⽅便起见,⼤家可以在这⾥把T 当成String,即String 在类中怎么⽤,那T 在类中就可以怎么⽤!所以下⾯的:定义变量,作为返回值,作为参数传⼊的定义就很容易理解了。
(3)使⽤泛型类
下⾯是泛型类的⽤法:
⾸先,是构造⼀个实例: 01. //定义  02. class  Point<T>{// 此处可以随便写标识符号  03.    private  T x ;        04.    private  T y ;        05.    public  void  setX(T x){//作为参数  06.        this .x = x ;  07.    }  08.    public  void  setY(T y){  09.        this .y = y ;  10.    }  11.    public  T getX(){//作为返回值  12.        return  this .x ;  13.    }  14.    public  T getY(){  15.        return  this .y ;  16.    }  17. };  18. //IntegerPoint 使⽤  19. Point<Integer> p = new  Point<Integer>() ;  20. p.setX(new  Integer(100)) ;  2
1. System.out.X());    22.  23. //FloatPoint 使⽤  24. Point<Float> p = new  Point<Float>() ;  25. p.setX(new  Float(100.12f)) ;  26. System.out.X());
[java]
01. //定义变量  02. private  T x ;  03. //作为返回值  04. public  T getX(){  05.    return  x ;    06. }    07. //作为参数  08. public  void  setX(T x){    09.    this .x = x ;    10. }
[java]
01. //IntegerPoint 使⽤  02. Point<Integer> p = new  Point<Integer>() ;  03. p.setX(new  Integer(100)) ;  04. System.out.X());    05.  06. //FloatPoint 使⽤  07. Point<Float> p = new  Point<Float>() ;  08. p.setX(new  Float(100.12f)) ;  09. System.out.X());
[java]
01. Point<String> p = new  Point<String>() ;
这⾥与普通构造类实例的不同之点在于,普通类构造函数是这样的:Point p = new Point() ;
⽽泛型类的构造则需要在类名后添加上<String>,即⼀对尖括号,中间写上要传⼊的类型。java接口有没有构造方法
因为我们构造时,是这样的:class Point<T>,所以在使⽤的时候也要在Point 后加上类型来定义T 代表的意义。
然后在getVar ()和setVar ()时就没有什么特殊的了,直接调⽤即可。
从上⾯的使⽤时,明显可以看出泛型的作⽤,在构造泛型类的实例的时候:
尖括号中,你传进去的是什么,T 就代表什么类型。这就是泛型的最⼤作⽤,我们只需要考虑逻辑实现,就能拿给各种类来⽤。
前⾯我们提到ArrayList 也是泛型,我们顺便它的实现:
看到了吧,跟我们的Point 实现是⼀样的,这也就是为什么ArrayList 能够盛装各种类型的主要原因。
(4)使⽤泛型实现的优势
相⽐我们开篇时使⽤Object 的⽅式,有两个优点:
(1)、不⽤强制转换
(2)、在settVar()时如果传⼊类型不对,编译时会报错
可以看到,当我们构造时使⽤的是String,⽽在setVar 时,传进去Integer 类型时,就会报错。⽽不是像Object 实现⽅式⼀样,在运⾏时才会报强制转换错误。
2、多泛型变量定义及字母规范
(1)、多泛型变量定义
上在我们只定义了⼀个泛型变量T ,那如果我们需要传进去多个泛型要怎么办呢?
只需要在类似下⾯这样就可以了:
也就是在原来的T 后⾯⽤逗号隔开,写上其它的任意⼤写字母即可。想加⼏个就加⼏个,⽐如我们想加五个泛型变量,那应该是这样的:
举个粟⼦,我们在Point 上再另加⼀个字段name ,也⽤泛型来表⽰,那要怎么做?代码如下: [java]
01. //IntegerPoint 使⽤  02. Point<Integer> p = new  Point<Integer>() ;  03. //FloatPoint 使⽤  04. Point<Float> p = new  Point<Float>() ;
[java]
01. public  class  ArrayList<E>{  02.    …………  03. }
[java]
01. //使⽤Object 作为返回值,要强制转换成指定类型  02. Float floatX = (X();  03. //使⽤泛型时,不⽤强制转换,直接出来就是String  04. System.out.Var());
[java]
01. class  MorePoint<T,U>{  02. }
[java]
01. class  MorePoint<T,U,A,B,C>{  02. }
从上⾯的代码中,可以明显看出,就是在新添加的泛型变量U ⽤法与T 是⼀样的。
(2)、字母规范
在定义泛型类时,我们已经提到⽤于指定泛型的变量是⼀个⼤写字母:
当然不是的任意⼀个⼤写字母都可以。他们的意义是完全相同的,但为了提⾼可读性,⼤家还是⽤有意义的字母⽐较好,⼀般来讲,在不同的情境下使⽤的字母意义如下:
E — Element ,常⽤在java Collection ⾥,如:List<E>,Iterator<E>,Set<E>
K,V — Key ,Value ,代表Map 的键值对
N — Number ,数字
T — Type ,类型,如String ,Integer 等等
如果这些还不够⽤,那就⾃⼰随便取吧,反正26个英⽂字母呢。
再重复⼀遍,使⽤哪个字母是没有特定意义的!只是为了提⾼可读性
3、泛型接⼝定义及使⽤
在接⼝上定义泛型与在类中定义泛型是⼀样的,代码如下:
与泛型类的定义⼀样,也是在接⼝名后加尖括号;
(1)、使⽤⽅法⼀:⾮泛型类
但是在使⽤的时候,就出现问题了,我们先看看下⾯这个使⽤⽅法:[java]
01. class  MorePoint<T,U> {  02.    private  T x;  03.    private  T y;        04.  05.    private  U name;  06.  07.    public  void  setX(T x) {  08.        this .x = x;  09.    }  10.    public  T getX() {  11.        return  this .x;  12.    }  13.    …………  14.    public  void  setName(U name){  15.        this .name = name;  16.    }  17.  18.    public  U getName() {  19.        return  this .name;  20.    }  21. }  22. //使⽤  23. MorePoint<Integer,String> morePoint = new  MorePoint<Integer, String>();  24. morePoint.setName("harvic");  25. Log.d(TAG, "Name:" + Name());
[java]
01. class  Point<T>{  02.  …………  03. }
[java]
01. interface  Info<T>{        // 在接⼝上定义泛型    02.    public  T getVar() ; // 定义抽象⽅法,抽象⽅法的返回值就是泛型类型    03.    public  void  setVar(T x);  04. }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。