java之泛型
泛型出现的原因:集合中可以存储各种对象,会被自动被提升为Object类型,当我们在取出每一个对象时,需要进行相应的操作。但如果集合中存储着不同类型的元素,则会出现类型转换异常ClassCastException,所以在存储时,必须明确集合元素的类型。
1 public class GenericDemo { 2 public static void main(String[] args) { 3 List list = new ArrayList(); 4 list.add("abc"); 5 list.add("oracle"); 6 list.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放 7 Iterator it = list.iterator(); 8 while(it.hasNext()){ 9 //需要打印每个字符串的长度,就要把迭代出来的对象转成String类型 10 String str = (String) it.next(); 11 System.out.println(str.length()); 12 } 13 } 14 } 15 程序在运行时发生了问题java.lang.ClassCastException 16 为什么会发生类型转换异常呢?我们来分析下: 17 由于集合中什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时 ClassCastException。怎么来解决这个问题呢?使用集合时,必须明确集合中元素的类型。这种方式称为:泛型。
1.1含有泛型的类:修饰符 class 类名<E>{},用于限制在创建对象时判断是否编译成功
1 class ArrayList<E>{ 2 public boolean add(E e){ } 3 public E get(int index){ } 4 } 5 使用格式:创建对象时,确定泛型的类型 6 例如,ArrayList<String> list = new ArrayList<String>(); 7 8 此时,变量E的值就是String类型 9 class ArrayList<String>{ 10 public boolean add(String e){ } 11 public String get(int index){ } 12 }
1.2含有泛型的接口:修饰符 interface 接口名<T>{}
1 4.2.2含有泛型的接口 2 定义格式:修饰符 interface接口名<代表泛型的变量> { } 3 例如,API中的Iterator迭代器接口 4 public interface Iterator<E> { 5 public abstract E next(); 6 } 7 8 使用格式: 9 1、定义类时确定泛型的类型 10 例如 11 public final class Scanner implements Iterator<String> { 12 public String next(){ 13 } 14 } 15 此时,变量E的值就是String类型。
1 2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型 2 3 例如 4 5 ArrayList<String> list = new ArrayList<String>(); 6 7 Iterator<String> it = list.iterator(); 8 9 此时,变量E的值就是String类型。 10 11 public interface Iterator<String> { 12 13 public abstract String next(); 14 15 }
2.泛型通配符
ArrayList<Student> s = new ArrayList<Student>();// 使用泛型明确Student类型 s.add(new Student("小红", 18)); s.add(new Student("小蓝", 19)); HashSet<Worker> w = new HashSet<Worker>();// 无序集合 w.add(new Worker("员工", 28)); w.add(new Worker("工作者", 29)); //传入参数 get(s); get(w);//运行异常到编译失败 } //泛型没有多态,写什么类型就是什么类型 // ?泛型通配符 //泛型限定符 ?extends 父类 只能传父类及其子类 //泛型限定符 ?super 父类 父类及其以上 //一个通用的方法,传的类不同时,找他们的父类,通过多态 public static void get(Collection<? > col){ //获取迭代器对象 Iterator<?> i=col.iterator(); while(i.hasNext()){ System.out.println(i.next());//object类型 //只能转换与Person类型的子父类 Person p=(Person)i.next(); p.work(); } }
注:当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。