泛型,就是一个参数化了的类或接口。在引入泛型之前,要在类中的方法支持多个数据类型,就需要对方法进行重载,在引入范型后,可以解决此问题(多态),更进一步可以定义多个参数以及返回值之间的关系。
下面定义个圆类:
class Point{
private Object x;//表示x坐标
private Object y;//表示y坐标
public Object getX(){
return this.x;
}
public void setX(Object x){
this.x=x;
}
public Object getY(){
return this.y;
}
public void setY(Object y){
this.y=y;
}
}
编写一个测试类:
public static void main(String[] args){
Point point=new Point();//声明一个Point对象
point.setX(30);//利用装箱操作:Integer--->Object
point.setY("北纬210度");//利用装箱操作:String--->Object
int x=(Integer)point.getX();//取出数据,变成String
int y=(Integer)point.getY();//取出数据,变成String
System.out.println("坐标表示:x="+x+",y="+y);
}
这样运行会发生数据类型不能转换的异常,传统的实现方式可能出现操作不当的隐患!
泛型可以解决数据类型的安全性问题,它主要的原理是在类声明的时候通过一个标识表示类中的某个属性的类型或者是某个方法的返回值或者参数的数据类型,这样在声明或者实例化时只要指定好需要的类即可
所以Point类我们可以这样定义泛型类
class Point<T>{
private T var;//T为定义的泛型类型
public T getVar(){
return this.var;
}
public void setVar(T var){
this.var=var;
}
}
下面测试类可这样写
public class GenericDemo07{
public static void main(String[] args){
Point<Integer> point=new Point<Integer>();//声明一个Point对象
point.setX(10);//只能设置Integer类型的数据,否则在编译时会报错
point.setY(20);//从而保护了数据类型的安全性
int x=point.getX();//省去了数据类型转换的麻烦
int y=point.getY();//省去了数据类型转换的麻烦
System.out.println("整数表示:x="+x+",y="+y);
}
}
- 在泛型的指定中,无法指定基本数据类型,必须指定类类型。
- 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。同一种类型可以有多个。
- 在泛型应用中最好在声明对象时指定其内部的数据类型,如:Point< String > p;也可以不指定其内部的数据类型,如:Point p,泛型对象在进行引用传递参数的时候,类型必须一致!
有界泛型
在引用传递中,泛型操作也可以设置一个泛型对象的范围上限和范围下限。范围上限使用extends关键字声明,表示参数化的数据类型可以是所指定的类型或者是此类型的子类型,而范围下限使用super进行声明,表示参数化的类型可以是此类型或者是此类型的父类型直至Object类.
public static void main(String[] args){
Info<Integer> info1=new Info<Integer>();
info1.setType(5);
func(info1);
Info<Float> info2=new Info<Float>();
info2.setType(5.5f);
func(info2);
/*Info<String> info3=new Info<String>();
info3.setType("张三");
func(info3);
//有错误:
//GenericDemo04.java:30: 无法将 GenericDemo04 中的
//func(Info<? extends java.lang.Number>) 应用于 (Info<java.lang.String>)
// func(info3);
// 1 错误
*/
}
//接收Info对象,范围上限设为Number,所以只能接受数字类型
public static void func(Info<? extends Number> info){
System.out.println("info:"+info);
}
通配符《?》
public static void main(String[] args){
Info<?> info=new Info<String>();
info.setType("我是小黄人");
func(info);
}
public static void func(Info<?> info){
System.out.println("info:"+info);
}
在使用通配符?的时候,只能接收内容,但不能修改内容
同样泛型也可以同样作用于方法,接口,数组上。
在JDK1.5之后,不仅仅可以声明泛型类,也可以声明泛型接口,声明泛型接口和声明泛型类的语法类似,也是在接口名称后加上< T >,如下格式所示:
[访问权限] interface 接口名称<泛型标识>{}
interface Info<T> {//在接口上定义泛型
public T getVar();
}
泛型的好处
1.泛型是一种强类型。其处理速度要比普通类快。
2.泛型用来解决创建和使用新的数据类型。泛型也使不同场合的代码重用更加方便。
3.与传统的类相比,泛型更加高效。泛型模板可以提供传统类不能实现的代码重用,在某些情况下可以少些很多代码。
4.与传统类只能使用通用类型(如object)不同,泛型可以指定使用的类型,提供更好的类型保护。
5.性能和类型安全性大大提高。