您的位置:首页 > 编程语言 > Java开发

Java中的泛型

2016-01-08 00:00 691 查看
1,为什么使用泛型?

泛型(Generic)是在JDK1.5之后增加的数据。

例如,现在要求设计一个表示坐标点的类,坐标有X和Y组成,坐标的表示有三种:

整数表示:x=10,y=15 ;

小数表示:x=10.5,y=15.5 ;

字符串表示:x=”东经120度”,y=”北纬30度”;

那么应该如何设计该类

a,首先应该设计一个表示坐标点的类----Point,定义两个属性表示x坐标y坐标,但是x和y中保存的数据类型有3种(int , float , String),要想使用一个类型同时接收三个数据类型,则现在使用Object进行接收——Object类可以接收任何数据类型的数据,都会进行自动向上转型操作。

int——自动装箱成Integer——向上转型使用Object接收;

float——自动装箱成Float——向上转型使用Object接收;

String——向上转型使用Object接收;





package org.panda.Generic;

class Point					//定义一个表示坐标点的类
{
private Object x ;		//声明一个Object类型属性
private Object y ;		//声明一个Object类型属性
/*
public Point(Object x,Object y)	//声明构造方法,给类中属性赋值
{
this.x = x ;				//给类中属性赋值
this.y = y ;
}
*/
public void setX(Object x)
{
this.x = x ;
}
public void setY(Object y)
{
this.y = y ;
}
public Object getX()
{
return x ;
}
public Object getY()
{
return y ;
}
}
public class GenericDemo01
{
public static void main(String[] args)
{
Point p = new Point();
p.setX(10) ;		//自动装箱成Integer,向上转型使用Object接收
p.setY(20) ;		//自动装箱成Integer,向上转型使用Object接收
//取出数据,先变成Integer再自动拆箱
System.out.println("X坐标:"+p.getX()+"Y坐标:"+p.getY()) ;

p.setX(10.5f);
p.setY(20.5f  );
//取出数据,先变成Float再自动拆箱
System.out.println("X坐标:"+(Float)p.getX()+"Y坐标:"+(Float)p.getY()) ;

p.setX("东经120度") ;				//字符串类型不用装箱拆箱
p.setY("北纬30度") ;				//字符串类型不用装箱拆箱
//取出数据,自动拆箱
System.out.println("X坐标:"+p.getX()+"Y坐标:"+p.getY());
/*
p.setX(10);
p.setY("东经120度");
System.out.println("X坐标:"+(Integer)p.getX()+"Y坐标:"+p.getY());
*/
}
}
/*
class Point<T>				//[访问权限] class 类名称<泛型类型>
{
private T var ;			//[访问权限] 泛型类型	变量;
public void setVar(T var)	//[访问权限] 返回值类型 setVar(泛型类型 变量)
{
this.var = var ;
}
public T getVar()			//[访问权限] 泛型类型 getVar()
{
return var ;
}
}
*/


输出结果是:

X坐标:10Y坐标:20
X坐标:10.5Y坐标:20.5
X坐标:东经120度Y坐标:北纬30度

看似以上代码已经解决问题,但是隐藏着巨大漏洞。会出现数据类型不统一的问题。并且传统方法也会出现操作不当的情况。

泛型可以解决数据类型的安全性问题。其原理是在类声明的时候通过一个标识表示类中某个属性或者某个方法的返回值及参数类型。这样在类声明和实例化的时候只需要指定需要的类型即可。

泛型定义格式:

[访问权限] class 类名称<泛型类型1,泛型类型2。。。泛型类型n>{}

[访问权限] 泛型类型标识 变量名称 ;

[访问权限] 泛型类型标识 方法名称(){} ;

[访问权限] 返回值类型声明 方法名(泛型类型名称 变量名称){}

泛型对象的定义:

类名称<具体类> 对象名称 = new 类名称<具体类>() ;





按照以上格式定义一个泛型Point类

package org.panda.Generic;

class P<T>					//定义一个类
{
private T var ;			//定义一个属性,var的类型由T决定,即 由外部决定
public void setVar(T var)	//定义一个set方法 设置的类型由外部决定
{
this.var = var ;
}
public T getVar()		//定义一个get方法,方法返回值类型由外部巨鼎
{
return var ;
}

public P(T var)
{
this.var = var ;
}

}
public class GenericDemo02
{
public static void main(String[] args)
{
/*
P<String> p = new P<String>() ;	//外部决定var类型是String类型
p.setVar("1234");
System.out.println(p.getVar());
System.out.println(p.getVar().length()) ;		//length()是方法。对象.方法()
//p.setVar(123);								//当输入的var数据不是Sring类型,则会报错
System.out.println(p.getVar());
*/
P<String> p = new P<String>("IronMan") ;
System.out.println(p.getVar());
}
}


package org.panda.Generic;

class Point1<T>					//定义一个类
{
private T x ;				//定义一个变量,变量x的数据类型T由外部决定
private T y ;				//定义一个变量,变量y的数据类型T由外部决定

public void setX(T x)		//声明一个set方法,设置的类型由外部决定
{
this.x = x ;
}
public void setY(T y)
{
this.y = y ;
}
public T getX()				//声明一个get方法,设置的类型由外部决定
{
return x ;
}
public T getY()
{
return y ;
}
}
public class GenericDemo03
{
public static void main(String[] args)
{
Point1<Integer> p1 = new Point1<Integer>() ;
p1.setX(10) ;			//自动装箱成Integer类型 int---->Integer
p1.setY(20) ;			//自动装箱成Integer类型 int---->Integer
//直接自动拆箱 	Integer---->int
System.out.println("x坐标:"+p1.getX()+",y坐标:"+p1.getY());

Point1<Float> p2 = new Point1<Float>() ;	//声明并实例化对象 外部设置T的数据类型是Float
p2.setX(10.5F) ;		//自动装箱成Float类型 float---->Float
p2.setY(20.5F) ;		//自动装箱成Float类型 float---->Float
System.out.println("x坐标:"+p2.getX()+",y坐标:"+p2.getY());

Point1<String> p3 = new Point1<String>() ;	//声明并实例化对象 外部设置T类型为String类型
p3.setX("东经120度");
p3.setY("北纬30度");
//p3.setX(10);				//----->数据类型不匹配,编译无法通过
System.out.println("x坐标:"+p3.getX()+",y坐标:"+p3.getY());
/*
以上这个程序减少了类型转换的代码,而且更加安全,如果外部输入数据类型跟泛型类型不匹配,则编译报错。
*/

}
}


在泛型的应用中最好在 声明类对象 的时候就指定好内部的数据类型,也可以不指定
当没有指定泛型数据类型的时候,java为了保证依然可以运行,会将K,V自动设置成Object类型,
这样一来就可以接收任意数据类型。所有的泛型信息都会被擦除,出现警告

package org.panda.Generic;

class Point2<K,V>			//定义多个泛型,泛型类型之间加”,“
{
private K x ;
private V y ;
public Point2(K x,V y)	//定义构造方法
{
this.x = x ;
this.y = y ;
}
public void setX(K x)
{
this.x = x ;
}
public void setY(V y)
{
this.y = y ;
}
public K getX()
{
return x ;
}
public V getY()
{
return y ;
}
}
public class GenericDemo04
{
public static void main(String[] args)
{
Point2<Integer,Float> p1 = null ;		  //声明类对象
p1 = new Point2<Integer,Float>(10,15.5f) ;//实例化类对象
System.out.println("x:"+p1.getX()+"y:"+p1.getY());
}
}


package org.panda.Generic;

class Info2<T>
{
private T var ;
public void setVar(T var)
{
this.var = var ;
}
public T getVar()
{
return this.var ;
}
}
public class GenericDemo07
{
public static void main(String[] args)
{
Info2<String> i1 = new Info2<String>() ;
Info2<Object> i2 = new Info2<Object>() ;
Info2<Integer> i3 = new Info2<Integer>() ;
i1.setVar("IronMan") ;
i2.setVar(10) ;
i3.setVar(20) ;
fun(i1) ;
fun(i2) ;
//fun(i3) ;
}
public static void fun(Info2<? super String> temp)//定义下限,只能接收String和Object类泛型
{
System.out.println(temp);
}
}


package org.panda.Generic;

class Info1<T>
{
private T var ;
public void setVar(T var)
{
this.var = var ;
}
public T getVar()
{
return this.var ;
}
public String toString()
{
return this.var.toString() ;
}
}
public class GenericDemo06
{
public static void main(String[] args)
{
Info1<Integer> i1 = new Info1<Integer>() ;
Info1<Float> i2 = new Info1<Float>() ;
i1.setVar(10) ;
i2.setVar(10.5f) ;
System.out.println(i1.getVar()+","+i2.getVar());
fun(i1) ;
fun(i2) ;
}
public static void fun(Info1<? extends Number> temp)//定义上限,只能接收Number类型泛型
{
System.out.println(temp);
}
}


2,通配符

匹配任意类型的通配符

在开发中,对象的引用传递是最常见的。但是如果在泛型类中操作。在进行引用传递时,泛型类型必须匹配才能传递,否则不能传递。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: