------- android培训、java培训、期待与您交流! ----------
(一)泛型的引出:
可以通过以下代码了解:
比如设计一个表示坐标点的类,坐标有X和Y组成,坐标的表示方法有三种:整型表示:x=10,y=20;小数表示:x=10.5,y=20.6;字符串:x=“东经180度”、y=“北纬220度”?
大概许多人会这样设计:
class Point{
private Object x ; // 表示X坐标
private Object y ; // 表示Y坐标
public void setX(Object x){
this.x = x ;
}
public void setY(Object y){
this.y = y ;
}
public Object getX(){
return this.x ;
}
public Object getY(){
return this.y ;
}
};
但是这样合理吗?如果我有以下代码呢?
public class GenericsDemo04{
public static void main(String args[]){
Point p = new Point() ; // 声明一个Point的对象
p.setX(10) ; // 利用自动装箱操作:int --> Integer --> Object
p.setY("北纬210度") ; // String --> Object
int x = (Integer)p.getX() ; // 取出数据先变为Integer,之后自动拆箱
int y = (Integer)p.getY() ; // 取出数据先变为Integer,之后自动拆箱
System.out.println("整数表示,X坐标为:" + x) ;
System.out.println("整数表示,Y坐标为:" + y) ;
}
};
传统的实现方法就有可能出现操作不当的情况。本程序就是数据类型不统一造成的。
泛型就可以解决数据类型的安全问题的。
原理:在类的声明时候通过一个标识表示类中的某一个属性的类型或是某个方法的返回值及参数类型。这样只要在类声明或实例化的时候指定好需要的类型即可。
格式:[访问权限] class 类名<泛型类型1,泛型类型2,….泛型类型3>{
[访问权限] 泛型标识 变量名;
[访问权限] 泛型类型标识 方法名(){}
[访问权限] 返回值类型声明 方法名(泛型类型标识 变量名){}
}
泛型对象定义格式:类名<具体类> 对象名=new 类名<具体类>();
这样实现代码就最好了:
class Point<T>{
private T x ; // 表示X坐标
private T y ; // 表示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 ;
}
};
public class GenericsPoint{
public static void main(String args[]){
Point<Integer> p = new Point<Integer>() ;
p.setX(10) ; // 利用自动装箱操作:int --> Integer
p.setY("北纬210度") ; // 利用自动装箱操作:int --> Integer
int x = p.getX() ; // 自动拆箱
int y = p.getY() ; // 自动拆箱
System.out.println("整数表示,X坐标为:" + x) ;
System.out.println("整数表示,Y坐标为:" + y) ;
}
};
以上是将var变量设置成String类型,当然,也可以设置成Integer,如果设置的内容和指定的泛型不一致,则编译时将会出错;使代码更安全。
(二)通配符 “?”
在开发中对象的引用传递是最常见的,但是如果在泛型类的操作中,进行引用传递是泛型类型必须匹配才可以传递,否则是无法传递的。
实例:Public static void main(String args[])
{
Collection<String> collection = newArrayList();
collection.add("abc");
printCollection(collection);
}
public static void printCollection(Collection<?> collection)
{
//collection.add(1);这句代码会报错,比如传进来的是一个参数化类型为String的集体,这是不合理的。
collection.size(); //这句代码可以通过
for(Object obj: collection) //打印集合中的每一个对象
{
System.out.println(obj);
}
}
使用?通配符可以引用各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法,在查JDK文档时,在参数里如果有<E>则表示这个方法与类的参数化有关。还有,通配符只能接收不能修改:
比如:Info<?> var=new Info<String>();这样编译时会出错的
泛型中的?通配符的扩展
• 限定通配符的上边界:
o 正确:Vector<? extends Number> x = new Vector<Integer>();//限定为Number或其子类
o 错误:Vector<? extends Number> x = new Vector<String>();
• 限定通配符的下边界:
o 正确:Vector<? super Integer> x = new Vector<Number>();//限定为Number或父类
o 正确:Vector<? super Integer> x = new Vector<Byte>();
• 提示:限定通配符总是包括自己。
(三)泛型的其他应用:
在JDK1.5之后,不仅仅可以声明泛型类,可以以声明泛型接口,生明泛型接口和声明泛型类的语法类似,在接口名称后加上<T>,
格式:[访问权限] interface 接口名称<泛型标识>{}
泛型数组:
使用泛型方法是,也可以传递或返回泛型数组
public class GenericsDemo30{
public static void main(String args[]){
Integer i[] = fun1(1,2,3,4,5,6) ; // 返回泛型数组
fun2(i) ;
}
public static <T> T[] fun1(T...arg){ // 接收可变参数
return arg ; // 返回泛型数组
}
public static <T> void fun2(T param[]){ // 输出
System.out.print("接收泛型数组:") ;
for(T t:param){
System.out.print(t + "、") ;
}
}
};
可变参数:
有的时候在设计方法时无法确定将来别人会传入的参数个数。JDK1.5增加了新特性可变参数,在函数中只声明参数类型,不规定个数。方法接受的参数实际上是一个数组,可以在方法中遍历数组。可变参数只能被定义为函数的最后一个形参。语法格式: 返回值 函数名(参数类型… 形参名)。