泛型介绍

各种泛型定义及使用

1、泛型类定义及使用

我们先看看泛型的类是怎么定义的:

[java]view plaincopy

//定义  

class Point<T>{// 此处可以随便写标识符号   

private T x ;        

private T 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 ;  

    }  

};  

//IntegerPoint使用  

Point p =new Point<Integer>() ;   

p.setX(new Integer(100)) ;   

System.out.println(p.getX());    


//FloatPoint使用  

Point p =new Point<Float>() ;   

p.setX(new Float(100.12f)) ;   

System.out.println(p.getX());    

(1)、定义泛型:Point<T>

首先,大家可以看到Point<T>,即在类名后面加一个尖括号,括号里是一个大写字母。这里写的是T,其实这个字母可以是任何大写字母,大家这里先记着,可以是任何大写字母,意义是相同的。

(2)类中使用泛型

这个T表示派生自Object类的任何类,比如String,Integer,Double等等。这里要注意的是,T一定是派生于Object类的。为方便起见,大家可以在这里把T当成String,即String在类中怎么用,那T在类中就可以怎么用!所以下面的:定义变量,作为返回值,作为参数传入的定义就很容易理解了。

各种泛型定义及使用

1、泛型类定义及使用

我们先看看泛型的类是怎么定义的:

[java]view plaincopy

//定义  

class Point<T>{// 此处可以随便写标识符号   

private T x ;        

private T 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 ;  

    }  

};  

//IntegerPoint使用  

Point p =new Point<Integer>() ;   

p.setX(new Integer(100)) ;   

System.out.println(p.getX());    


//FloatPoint使用  

Point p =new Point<Float>() ;   

p.setX(new Float(100.12f)) ;   

System.out.println(p.getX());    

前面我们提到ArrayList也是泛型,我们顺便它的实现:

[java]view plaincopy

public class ArrayList<E>{  

    …………  

}  

看到了吧,跟我们的Point实现是一样的,这也就是为什么ArrayList能够盛装各种类型的主要原因。

相比我们开篇时使用Object的方式,有两个优点:

(1)、不用强制转换

[java]view plaincopy

//使用Object作为返回值,要强制转换成指定类型  

Float floatX = (Float)floatPoint.getX();  

//使用泛型时,不用强制转换,直接出来就是String  

System.out.println(p.getVar());   

(2)、在settVar()时如果传入类型不对,编译时会报错

可以看到,当我们构造时使用的是String,而在setVar时,传进去Integer类型时,就会报错。而不是像Object实现方式一样,在运行时才会报强制转换错误。

2、多泛型变量定义及字母规范

(1)、多泛型变量定义

上在我们只定义了一个泛型变量T,那如果我们需要传进去多个泛型要怎么办呢?

只需要在类似下面这样就可以了:

[java]view plaincopy

class MorePoint<T,U>{  

}  

也就是在原来的T后面用逗号隔开,写上其它的任意大写字母即可。想加几个就加几个,比如我们想加五个泛型变量,那应该是这样的:

[java]view plaincopy

class MorePoint<T,U,A,B,C>{  

}  

举个粟子,我们在Point上再另加一个字段name,也用泛型来表示,那要怎么做?代码如下:

[java]view plaincopy

class MorePoint<T,U> {  

private T x;  

private T y;         


private U name;  


public void setX(T x) {  

this.x = x;  

    }  

public T getX() {  

return this.x;  

    }  

    …………  

public void setName(U name){  

this.name = name;  

    }  


public U getName() {  

return this.name;  

    }  

}  

//使用  

MorePoint morePoint =new MorePoint<Integer, String>();  

morePoint.setName("harvic");  

Log.d(TAG,"morPont.getName:" + morePoint.getName());  

从上面的代码中,可以明显看出,就是在新添加的泛型变量U用法与T是一样的。

2)、字母规范

在定义泛型类时,我们已经提到用于指定泛型的变量是一个大写字母:

[java]view plaincopy

class Point<T>{  

 …………  

}  

当然不是的!!!!任意一个大写字母都可以。他们的意义是完全相同的,但为了提高可读性,大家还是用有意义的字母比较好,一般来讲,在不同的情境下使用的字母意义如下:

 E — Element,常用在java Collection里,如:List<E>,Iterator<E>,Set<E>

 K,V — Key,Value,代表Map的键值对

 N — Number,数字

 T — Type,类型,如String,Integer等等

如果这些还不够用,那就自己随便取吧,反正26个英文字母呢。

再重复一遍,使用哪个字母是没有特定意义的!只是为了提高可读性!!!!

3、泛型接口定义及使用

在接口上定义泛型与在类中定义泛型是一样的,代码如下:

[java]view plaincopy

interface Info<T>{        // 在接口上定义泛型    

public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型    

public void setVar(T x);  

}    

与泛型类的定义一样,也是在接口名后加尖括号;

4、泛型函数定义及使用

上面我们讲解了类和接口的泛型使用,下面我们再说说,怎么单独在一个函数里使用泛型。比如我们在新建一个普通的类StaticFans,然后在其中定义了两个泛型函数:

[java]view plaincopy

public class StaticFans {  

//静态函数  

public static  <T> void StaticMethod(T a){  

Log.d("harvic","StaticMethod: "+a.toString());  

    }  

//普通函数  

public  <T> void OtherMethod(T a){  

Log.d("harvic","OtherMethod: "+a.toString());  

    }  

}  

上面分别是静态泛型函数和常规泛型函数的定义方法,与以往方法的唯一不同点就是在返回值前加上<T>来表示泛型变量。其它没什么区别。


5、其它用法:Class<T>类传递及泛型数组

(1)、使用Class<T>传递泛型类Class对象

有时,我们会遇到一个情况,比如,我们在使用JSON解析字符串的时候,代码一般是这样的

[java]view plaincopy

public static List<SuccessModel> parseArray(String response){  

List modelList = JSON.parseArray(response, SuccessModel.class);  

return modelList;  

}  

其中SuccessModel是自定义的解析类,代码如下,其实大家不用管SuccessModel的定义,只考虑上面的那段代码就行了。写出来SuccessModel的代码,只是不想大家感到迷惑,其实,这里只是fastJson的基本用法而已。

这段代码的意义就是根据SuccessModel解析出List<SuccessModel>的数组。

[java]view plaincopy

public class SuccessModel {  

private boolean success;  


public boolean isSuccess() {  

return success;  

    }  


public void setSuccess(boolean success) {  

this.success = success;  

    }  

}   

那现在,我们把下面这句组装成一个泛型函数要怎么来做呢?

[java]view plaincopy

public static List<SuccessModel> parseArray(String response){  

List modelList = JSON.parseArray(response, SuccessModel.class);  

return modelList;  

}  

首先,我们应该把SuccessModel单独抽出来做为泛型变量,但parseArray()中用到的SuccessModel.class要怎么弄呢?

先来看代码:

[java]view plaincopy

public static <T> List<T> parseArray(String response,Class<T> object){  

    List<T> modelList = JSON.parseArray(response, object);  

return modelList;  

}  

注意到,我们用的Class<T> object来传递类的class对象,即我们上面提到的SuccessModel.class。

这是因为Class<T>也是一泛型,它是传来用来装载类的class对象的,它的定义如下:

[java]view plaincopy

public final class Class<T> implements Serializable {  

    …………  

}  

通过Class<T>来加载泛型的Class对象的问题就讲完了,下面来看看泛型数组的使用方法吧。

(2)、定义泛型数组

在写程序时,大家可能会遇到类似String[] list = new String[8];的需求,这里可以定义String数组,当然我们也可以定义泛型数组,泛型数组的定义方法为 T[],与String[]是一致的,下面看看用法:

[java]view plaincopy

//定义  

public static <T> T[] fun1(T...arg){  // 接收可变参数    

return arg ;            // 返回泛型数组    

}    

//使用  

public static void main(String args[]){    

Integer i[] = fun1(1,2,3,4,5,6) ;  

       Integer[] result = fun1(i) ;  

}    

我们先看看 定义时的代码:

[java]view plaincopy

public static <T> T[] fun1(T...arg){  // 接收可变参数    

return arg ;            // 返回泛型数组    

}    

首先,定义了一个静态函数,然后定义返回值为T[],参数为接收的T类型的可变长参数。如果有同学对T...arg的用法不了解,可以去找下JAVA 可变长参数方面的知识。

由于可变长参数在输入后,会保存在arg这个数组中,所以,我们直接把数组返回即可。

转自:http://blog.csdn.net/harvic880925/article/details/49872903

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,563评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,694评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,672评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,965评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,690评论 6 413
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 56,019评论 1 329
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 44,013评论 3 449
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,188评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,718评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,438评论 3 360
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,667评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,149评论 5 365
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,845评论 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,252评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,590评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,384评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,635评论 2 380

推荐阅读更多精彩内容