Java新特性2 -- 泛型
来源:互联网 发布:姿态变换矩阵 编辑:程序博客网 时间:2024/05/20 21:49
在我们开发中,经常会用到集合,我们也知道集合是用来存储元素的,但它却没有规范存储元素的具体类型,为了是我们的程序更规范化,就应当使用泛型了。
泛型是提供给javac编辑器使用的,可以限定集合中的输入类型,让编译器挡住源程序的非法输入,编辑器编译带类型说明的集合时会去除掉“类型”信息,是程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据,例如:用反射得到集合,在调用其add方法即可。
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2= new ArrayList<Integer>();
System.out.println(list1.getClass() == list1.getClass());
打印true,就表示泛型只提供给编译器使用,运行期是不受影响,那我们想在list2中添加String类型的对象,如果我们直接add方法,编译器会报错。那我们怎么办?我们可以使用反射得到集合,然后调用其add方法就可以添加String类型的对象
list2.getClass().getMethod("add",
Object.class).invoke(list2, "abc");
System.out.println(collection3.get(0));
这样我们就在list2中添加了一个String类型的对象。
下面我们来简单了解一下泛型
l 术语,例如ArrayList<E>类定义和ArrayList<Integer>类定义
n 整个称为ArrayList<E>泛型类型
n ArrayList<E>中的E称为类型变量或类型参数
n 整个ArrayList<Integer>称为参数化的类型
n ArrayList<Ingerger>中的Integer称为类型参数的实例或实际类型参数
n ArrayList<Integer>中<>念着typeof
n ArrayList称为原始类型
l 参数化类型与原始类型的兼容性
n 参数化类型可以引用一个原始类型的对象,编译报告警告,但没有错,例如:Collection<String> c = new Vector();
n 原始类型可以引用一个参数化类型的对象,编译报告警告,但没有错,例如:Collection c = new Vector<String> ();
l 参数化类型不考虑类型参数的继承关系:
n Vector<String> v = new Vector<Object>(); 错误
n Vector< Object > v = new Vector<String>(); 错误
l 在创建数组实例时,数组的原始不能使用参数化的类型,例如:
Vector<Integer> v[] = new Vector<Integer>[10];错误
练习:定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义?
错误方式:
public void printCollection(Collection<Object> collection){
for(Object obj : collection){
System.out.println(obj);
}
}
为什么错呢?
由于泛型不考虑类型参数的继承关系,如果我们调用这个方式传递的是
Collection<Integer> list2= new ArrayList<Integer>();
那肯定会报错,这个方法是不能打印任意参数化类型的集合
正确方式:
public void printCollection(Collection<?> collection){
for(Object obj : collection){
System.out.println(obj);
}
}
这个方法能打印出任意参数化类型的集合,但是collection不能调用add方法,为什么?
因为使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法,例如add方法就是与参数化有关的方法。
使用?通配符表示可以使用任意参数化类型,如果我们需要一个范围,那该怎么办呢?在?通配符中还有两个上边界与下边界,分别为:限定通配符上边界和限定通配符下边界。
l 限定通配符上边界
Vector<? extends Number> x = new Vector<Integer>(); 正确
Vector<? extends Number> x = new Vector<String>(); 错误
l 限定通配符下边界
Vector<? super Integer> x = new Vector<Number>(); 正确
Vector<? super Integer> x = new Vector<Byte>(); 错误
我们了解泛型的一些知识后,现在我们来自己定义泛型,泛型方法与泛型类
l 自定义泛型方法
//将任意类型的数组中的所有元素填充为相应类型的某个对象
private <T> void fillArray(T[] a,T obj){
for(int i=0;i<a.length;i++){
a[i] = obj;
}
}
//将Object对象转化成任意对象
private <T> T autoConvert(Object obj){
return (T)obj;
}
//将任意类型的数组调换位置
private <T> void swap(T[] a,int i,int j){
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
private <T> T add(T x,T y){
return null;
}
调用代码:
add(3,5);
Number x1 = add(3.5,3);
Object x2 = add(3,"abc");
返回类型必须为我们传递参数的最小公共类型
String[] strArray=new String[]{"a","b","c"};
swap(strArray,1,2); //这样就可以实现数组交换
但是下面这种情况是不行
int[] intArray=new int[]{1,2,3};
swap(intArray,1,2);
因为只有引用类型才能作为泛型方法的实际参数,那为什么上面add怎么就可以呢?因为add方法中传递int值会自动装箱和拆箱,而我们这里是一个int[]类型是不会自动装箱和拆箱,因此编译器会报错
我们在定义泛型是可以使用extends限定符,我们可以参考java.lang.Class类的一个方法:
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
并且可以用&来指定多个边界,如:<V extends Serializable&Thread>
普通方法、构造方法和静态方法中都可以使用泛型;也可以抛出异常泛型,例如:
public <T extentds Exception> exceptionTest throws T{
try{
}catch(Exception e){
throw (T)e;
}
}
在泛型中可以同时有多个类型参数,在定义他们的尖括号中用逗号分,例如:
public <K,V> V getValue(K key){}
l 自定义泛型类型
如果类的实例对象的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型。例如:
public class GenericDao<E> {
public void add(E x){
}
public E findById(int id){
return null;
}
public void delete(E obj){
}
public void delete(int id){
}
public void update(E obj){
}
public static <E> void update2(E obj){
}
public E findByUserName(String name){
return null;
}
public Set<E> findByConditions(String where){
return null;
}
}
注意:
n 在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型
n 当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类所共享,所以静态成员不应该有类级别的类型参数。
- Java新特性2 -- 泛型
- java新特性—泛型
- Java新特性:接口新特性
- jdk1.5的新特性(java泛型)
- jdk1.5的新特性(java泛型)
- Java 5.0 新特性总结 三 泛型
- Java 5 新特性——泛型
- 黑马程序员----------Java新特性反射 泛型
- java jdk多线程新特性2
- JAVA EE5 新特性
- Java 7 新特性
- Java新特性
- Java 7 新特性
- Java 7 新特性
- Java 新特性
- Java 7 新特性
- JAVA新特性笔记
- java新特性
- Chart图表入门
- PermGen space错误处理
- xiaocainiao!
- 什么是 RSSI RSCP
- DB2查找重复记录SQL
- Java新特性2 -- 泛型
- Could not determine type for: java.util.Boolean, at table:出错的处理
- Runtime.getRuntime().addShutdownHook
- 我的淘宝openAPI之旅
- 把字串转成ASCII
- Web优化的14条法则
- 条款7:为多态基类声明VIRTUAL析构函数
- Web优化的14条法则之一个人看法
- Web优化的14条法则及我们的实际应用