26、泛型
泛型的概念
在编写集合相关代码时在eclipse里面总有一些黄色警告,在不使用注解的情况下,使用泛型之后,就不会有这些黄色警告了。
通过API可以看到Collection,List,ArrayList,这几个类里面都有,这个就是泛型,里面的E可以是任何引用数据类型,使用泛型指明了数据类型之后,这个集合里面只能存储这种数据类型的对象。
不使用泛型时,要进行多次类型强制转换
package com.monkey1024.generic; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.monkey1024.bean.Person; /** * 不使用泛型的缺点 * */ public class GenericTest01 { public static void main(String[] args) { List list = new ArrayList(); //如果不使用泛型可以像list中存放不同的数据类型 list.add("monkey"); list.add(1024); list.add(new Person("刘德华", 51)); Iterator iter = list.iterator(); while(iter.hasNext()){ //只能做大量的类型判断 Object obj = iter.next(); if(obj instanceof String){ String s = (String)obj; } if(obj instanceof Integer){ Integer i = (Integer)obj; } if(obj instanceof Person){ Person p = (Person)obj; } } } }
使用泛型之后:
package com.monkey1024.generic; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.monkey1024.bean.Person; /** * 使用泛型 * */ public class GenericTest02 { public static void main(String[] args) { //前后数据类型保持一致 List<Person> list = new ArrayList<Person>(); //jdk7加入的菱形泛型 List<Person> list7 = new ArrayList<>(); //下面代码编译报错 // list.add("monkey"); // list.add(1024); list.add(new Person("刘德华", 51)); Iterator<Person> iter = list.iterator(); while(iter.hasNext()){ Person p = (Person)iter.next(); } } }
泛型的优点
- 可以统一集合中的数据类型,提高安全性
- 可以减少强制类型转换
自定义泛型
通过JDK的源码可以看到,泛型一般写的都是或者,里面的T和E就是表示使用者指定的类型。可以自己定义一个使用泛型的类
package com.monkey1024.generic; /** * 自定义泛型 * 类上面使用泛型 * @param <T> */ public class Value<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } //方法的泛型最好与类一致,如果不一致需要在方法上面声明泛型 public<M> void show(M m){ System.out.println(m); } }
泛型通配符
在实际工作当中,有可能通过调用某个方法来接受一个返回值List的数据,这样就不太好确定返回值中的数据类型,这样可以使用泛型通配符<?>
List<?> list = new ArrayList<Integer>();//=号右边可能是通过调用某个方法返回的List
使用泛型通配符限定子类或者父类
? extends E
向下限定,E及其子类,可以存储当前类型的子类
? super E
向上限定,E及其父类,可以存储当前类型的父类
定义一个Student类继承Person
package com.monkey1024.bean; public class Student extends Person { public Student() { super(); } public Student(String name, int age) { super(name, age); } }
在List中方法addAll是限定了子类(? extends E),定义测试类:
package com.monkey1024.generic; import java.util.ArrayList; import java.util.List; /** * ? extends E 向下限定,E及其子类,可以存储当前类型的子类 * ? super E 向上限定,E及其父类,可以存储当前类型的父类 * */ public class GenericTest03 { public static void main(String[] args) { List<Person> personList = new ArrayList<>(); personList.add(new Person("张三", 23)); personList.add(new Person("李四", 24)); personList.add(new Person("王五", 25)); List<Student> studentList = new ArrayList<>(); studentList.add(new Student("赵六", 26)); studentList.add(new Student("周七", 27)); //因为studentList中存放的Student是Person类的子类,所以可以将studentList放入personList中 personList.addAll(studentList); System.out.println(personList); } }