java泛型类使用_Java泛型详解:和Class的使用。泛型类,泛型方法的详细使用实例...

一、引入

1、泛型是什么

首先告诉大家ArrayList就是泛型。那ArrayList能完成哪些想不到的功能呢?先看看下面这段代码:

[java]view

plaincopy

ArrayListstrList=newArrayList();

ArrayListintList=newArrayList();

ArrayListdoubleList=newArrayList();

大家对ArrayList很熟悉,这里构造了三个List,分别盛装String、Integer和Double;这就是ArrayList的过人之处:即各种类型的变量都可以组装成对应的List,而不必针对每个类型分别实现一个构建ArrayList的类。这里可能看不懂,开篇总是困难的,下面看看如果没有泛型的话,我们要怎么做;

2、没有泛型会怎样

先看下面这段代码:

我们实现两个能够设置点坐标的类,分别设置Integer类型的点坐标和Float类型的点坐标:

[java]view

plaincopy

//设置Integer类型的点坐标

classIntegerPoint{

privateIntegerx;//表示X坐标

privateIntegery;//表示Y坐标

publicvoidsetX(Integerx){

this.x=x;

}

publicvoidsetY(Integery){

this.y=y;

}

publicIntegergetX(){

returnthis.x;

}

publicIntegergetY(){

returnthis.y;

}

}

//设置Float类型的点坐标

classFloatPoint{

privateFloatx;//表示X坐标

privateFloaty;//表示Y坐标

publicvoidsetX(Floatx){

this.x=x;

}

publicvoidsetY(Floaty){

this.y=y;

}

publicFloatgetX(){

returnthis.x;

}

publicFloatgetY(){

returnthis.y;

}

}

那现在有个问题:大家有没有发现,他们除了变量类型不一样,一个是Integer一个是Float以外,其它并没有什么区别!那我们能不能合并成一个呢?

答案是可以的,因为Integer和Float都是派生自Object的,我们用下面这段代码代替:

[java]view

plaincopy

classObjectPoint{

privateObjectx;

privateObjecty;

publicvoidsetX(Objectx){

this.x=x;

}

publicvoidsetY(Objecty){

this.y=y;

}

publicObjectgetX(){

returnthis.x;

}

publicObjectgetY(){

returnthis.y;

}

}

即全部都用Object来代替所有的子类;

在使用的时候是这样的:

[java]view

plaincopy

ObjectPointintegerPoint=newObjectPoint();

integerPoint.setX(newInteger(100));

IntegerintegerX=(Integer)integerPoint.getX();

在设置的时候,使用new Integer(100)来新建一个Integer

[java]view

plaincopy

integerPoint.setX(newInteger(100));

然后在取值的时候,进行强制转换:

[java]view

plaincopy

IntegerintegerX=(Integer)integerPoint.getX();

由于我们设置的时候,是设置的Integer,所以在取值的时候,强制转换是不会出错的。

同理,FloatPoint的设置和取值也是类似的,代码如下:

[java]view

plaincopy

ObjectPointfloatPoint=newObjectPoint();

floatPoint.setX(newFloat(100.12f));

FloatfloatX=(Float)floatPoint.getX();

但问题来了:注意,注意,我们这里使用了强制转换,我们这里setX()和getX()写得很近,所以我们明确的知道我们传进去的是Float类型,那如果我们记错了呢?

比如我们改成下面这样,编译时会报错吗:

[java]view

plaincopy

ObjectPointfloatPoint=newObjectPoint();

floatPoint.setX(newFloat(100.12f));

StringfloatX=(String)floatPoint.getX();

不会!!!我们问题的关键在于这句:

[java]view

plaincopy

StringfloatX=(String)floatPoint.getX();

强制转换时,会不会出错。因为编译器也不知道你传进去的是什么,而floatPoint.getX()返回的类型是Object,所以编译时,将Object强转成String是成立的。必然不会报错。

而在运行时,则不然,在运行时,floatPoint实例中明明传进去的是Float类型的变量,非要把它强转成String类型,肯定会报类型转换错误的!

那有没有一种办法在编译阶段,即能合并成同一个,又能在编译时检查出来传进去类型不对呢?当然,这就是泛型。

下面我们将对泛型的写法和用法做一一讲解。

二、各种泛型定义及使用

1、泛型类定义及使用

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

[java]view

plaincopy

//定义

classPoint{//此处可以随便写标识符号

privateTx;

privateTy;

publicvoidsetX(Tx){//作为参数

this.x=x;

}

publicvoidsetY(Ty){

this.y=y;

}

publicTgetX(){//作为返回值

returnthis.x;

}

publicTgetY(){

returnthis.y;

}

};

//IntegerPoint使用

Pointp=newPoint();

p.setX(newInteger(100));

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

//FloatPoint使用

Pointp=newPoint();

p.setX(newFloat(100.12f));

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

先看看运行结果:

0961243b0317f4ca***769be88a700c06.jpg

从结果中可以看到,我们实现了开篇中IntegerPoint类和FloatPoint类的效果。下面来看看泛型是怎么定义及使用的吧。

(1)、定义泛型:Point

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

(2)类中使用泛型

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

[java]view

plaincopy

//定义变量

privateTx;

//作为返回值

publicTgetX(){

returnx;

}

//作为参数

publicvoidsetX(Tx){

this.x=x;

}

(3)使用泛型类

下面是泛型类的用法:

[java]view

plaincopy

//IntegerPoint使用

Pointp=newPoint();

p.setX(newInteger(100));

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

//FloatPoint使用

Pointp=newPoint();

p.setX(newFloat(100.12f));

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

首先,是构造一个实例:

[java]view

plaincopy

Pointp=newPoint();

这里与普通构造类实例的不同之点在于,普通类构造函数是这样的:Point p = new Point() ;

而泛型类的构造则需要在类名后添加上,即一对尖括号,中间写上要传入的类型。

因为我们构造时,是这样的:class Point,所以在使用的时候也要在Point后加上类型来定义T代表的意义。

然后在getVar()和setVar()时就没有什么特殊的了,直接调用即可。

从上面的使用时,明显可以看出泛型的作用,在构造泛型类的实例的时候:

[java]view

plaincopy

//IntegerPoint使用

Pointp=newPoint();

//FloatPoint使用

Pointp=newPoint();

尖括号中,你传进去的是什么,T就代表什么类型。这就是泛型的最大作用,我们只需要考虑逻辑实现,就能拿给各种类来用。

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

[java]view

plaincopy

publicclassArrayList{

…………

}

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

(4)使用泛型实现的优势

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

(1)、不用强制转换

[java]view

plaincopy

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

FloatfloatX=(Float)floatPoint.getX();

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

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

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

735745d002c256eca3584356dc172611.png

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

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

(1)、多泛型变量定义

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

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

[java]view

plaincopy

classMorePoint{

}

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

[java]view

plaincopy

classMorePoint{

}

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

[java]view

plaincopy

classMorePoint{

privateTx;

privateTy;

privateUname;

publicvoidsetX(Tx){

this.x=x;

}

publicTgetX(){

returnthis.x;

}

…………

publicvoidsetName(Uname){

this.name=name;

}

publicUgetName(){

returnthis.name;

}

}

//使用

MorePointmorePoint=newMorePoint();

morePoint.setName("harvic");

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

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

(2)、字母规范

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

[java]view

plaincopy

classPoint{

…………

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值