您的位置:首页 > 职场人生

黑马程序员_java泛型

2012-12-21 16:59 183 查看
------- android培训java培训、期待与您交流! ----------
java泛型的描述:

ArrayList<Integer> collection=new ArrayList<Integer> ();这就是泛型,JDK1.5的集合类希望你在定义集合时,

明确表示你要相集合中装哪种类型的数据(如上面的<Integer>),无法加入指定类型以外的数据。

泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去掉“类型信息”,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据,例如,用反射得到集合,再调用其add方法即可。

例如:

ArrayList<String> collection2=new ArrayList<String>();

ArrayList<Integer> collection3=new ArrayList<Integer>();

collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");

System.out.println(collection3.get(0));

System.out.println(collection3.getClass()==collection2.getClass());

输出的结果为abc true

泛型中的一些术语:

整个ArrayList<E>称为泛型类型

整个ArrayList<Integer>称为参数化的类型

ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数

ArrayList<Integer>中的<>念typeof

ArrayList称为原始类型

参数化类型与原始类型的兼容性:

参数化类型可以引用一个原始类型的对象,编译器报告警告,例如,

Collection<String> c=new Vector();

原始类型可以引用一个参数化类型的对象编译器报告警告,例如,

Collection c=new Vector<String>();

参数化类型不考虑类型参数的继承关系:

Vector<String> v=new Vector<Object>();//错误

Vector<Object> v=new Vector<String>();//也错误

在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

Vector<Integer> vectorList[]=new Vector<Integer>[10];

思考,下面代码会报错吗?

Vector v1=new Vector<String>();

Vector<Object> v=v1;

结果是不会报错,因为编译器是一行一行的扫描,编译器认为他们没有任何关系。

泛型中的?通配符

public static void printCollection2(Collection<?> collection){

System.out.println(collection.size());

for(Object obj : collection){

System.out.println(obj);

}

}

总结:使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。

泛型中的?通配符的扩展

限定通配符的上边界:

正确:Vector<? extends Number>x=new Vector<Integer>();

错误:Vector<? extends Number>x=new Vector<String>();

限定通配符的下边界:

正确:Vector<? super Integer>x=new Vector<Number>();

错误:Vector<? super Integer>x=new Vector<Byte>();

提示:限定通配符总是包括自己。

下面来写一个小例子:

package cn.itcast.day2;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

public class GenericTest {

public static void main(String[] args) throws Exception{

HashMap<String,Integer> maps=new HashMap<String,Integer>();

maps.put("zxx", 28);

maps.put("lhm", 35);

maps.put("flx", 33);

Set<Map.Entry<String,Integer>> entrySet=maps.entrySet();

//迭代entrySet

for(Map.Entry<String,Integer> entry : entrySet){

System.out.println(entry.getKey() + ":" + entry.getValue());

}

}

}

定义泛型:

如,private static <T> T add(T x,T y){

return null;

}

用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回值类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。

只有引用类型才能作为泛型方法的实际参数。

除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符,并且可以用&类指定多个边界,如<V extends Serializable & cloneable>void method(){}

普通方法,构造方法和静态方法中都可以使用泛型。

也可以用类型变量表示异常,称为参数异常,可以用于方法的throws列表中,但是不能用于catch子句中。

在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分开,例如:

public static<K,V> V getValue(K key){return map.get(key);}

如果类的实例对象中的多处用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式如下:

public class GenericDao<T>{

private T field1;

public void save(T obj){}

public T getByld(int d){}

}

类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的,例如,如下两种方式都可以:

GenericDao<String> dao=null;

new GenericDao<String>();

注意:在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。

当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态变量和静态方法调用。因为静态成员是被所有参数化的类型所共享的,所以静态成员不应该有类级别的类型参数。

------- android培训java培训、期待与您交流! ----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: