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 tX(Integer x){ 06. this .x = x ; 07. } 08. public void tY(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 tX(Float x){ 23. this .x = x ; 24. } 25. public void tY(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 的设置和取值也是类似的,代码如下:
但问题来了:注意,注意,我们这⾥使⽤了强制转换,我们这⾥tX ()和getX ()写得很近,所以我们明确的知道我们传进去的是Float 类型,那如果我们记错了呢?
⽐如我们改成下⾯这样,编译时会报错吗:
不会我们问题的关键在于这句:
强制转换时,会不会出错。因为编译器也不知道你传进去的是什么,⽽X()返回的类型是Object ,所以编译时,将Object 强转成String 是成⽴的。必然不会报错。
⽽在运⾏时,则不然,在运⾏时,floatPoint 实例中明明传进去的是Float 类型的变量,⾮要把它强转成String 类型,肯定会报类型转换错误的!
那有没有⼀种办法在编译阶段,即能合并成同⼀个,⼜能在编译时检查出来传进去类型不对呢?当然,这就是泛型。
下⾯我们将对泛型的写法和⽤法做⼀⼀讲解。
⼆、各种泛型定义及使⽤
1、泛型类定义及使⽤
我们先看看泛型的类是怎么定义的: 01. class ObjectPoint{ 02. private Object x ; 03. private Object y ; 04. public void tX(Object x){ 05. this .x = x ; 06. } 07. public void tY(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.tX(new Integer(100)); 03. Integer integerX=(X();
[java]
01. integerPoint.tX(new Integer(100));
[java]
01. Integer integerX=(X();多彩的活动作文400字
[java]
01. ObjectPoint floatPoint = new ObjectPoint(); 02. floatPoint.tX(new Float(100.12f)); 03. Float floatX = (X();
[java]
菠萝汤
01. ObjectPoint floatPoint = new ObjectPoint(); 02. floatPoint.tX(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 tX(T x){//作为参数 06. this .x = x ; 07. } 08. public void tY(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.tX(new Integer(100)) ; 2
1. System.out.X()); 22. 23. //FloatPoint 使⽤ 24. Point<Float> p = new Point<Float>() ; 25. p.tX(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 tX(T x){ 09. this .x = x ; 10. }
关于过年的诗[java]
01. //IntegerPoint 使⽤ 02. Point<Integer> p = new Point<Integer>() ; 03. p.tX(new Integer(100)) ; 04. System.out.X()); 05. 06. //FloatPoint 使⽤ 07. Point<Float> p = new Point<Float>() ; 08. p.tX(new Float(100.12f)) ; 09. System.out.X());
[java]
01. Point<String> p = new Point<String>() ;
这⾥与普通构造类实例的不同之点在于,普通类构造函数是这样的:Point p = new Point() ;
⽽泛型类的构造则需要在类名后添加上<String>,即⼀对尖括号,中间写上要传⼊的类型。
因为我们构造时,是这样的:class Point<T>,所以在使⽤的时候也要在Point 后加上类型来定义T 代表的意义。
然后在getVar ()和tVar ()时就没有什么特殊的了,直接调⽤即可。敏锐造句
从上⾯的使⽤时,明显可以看出泛型的作⽤,在构造泛型类的实例的时候:
尖括号中,你传进去的是什么,T 就代表什么类型。这就是泛型的最⼤作⽤,我们只需要考虑逻辑实现,就能拿给各种类来⽤。
前⾯我们提到ArrayList 也是泛型,我们顺便它的实现:
看到了吧,跟我们的Point 实现是⼀样的,这也就是为什么ArrayList 能够盛装各种类型的主要原因。
(4)使⽤泛型实现的优势
相⽐我们开篇时使⽤Object 的⽅式,有两个优点:
(1)、不⽤强制转换
(2)、在ttVar()时如果传⼊类型不对,编译时会报错
可以看到,当我们构造时使⽤的是String,⽽在tVar 时,传进去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 tX(T x) { 08. this .x = x; 09. } 10. public T getX() { 11. return this .x; 12. } 13. ………… 14. public void tName(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.tName("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 tVar(T x); 04. }