- 泛型又称为类型参数(parameterized type),jdk 1.5 之前只能用Object代替,jdk 1.5 之后使用泛型解决
- 所谓泛型就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型,这个类型参数将在使用时确定(根据传入的实际参数类型),例如List<String>表明这个List只能存放String类型的对象
- 使用泛型可以严格规定编程中使用某一类型,防止出现ClassCastException;泛型的参数必须是对象类型,不能是基本数据类型
- 泛型嵌套
public class GenericTest1 { @Test public void test1() { Map<String,Integer> map = new HashMap<>();// Map<K,V> Set<Map.Entry<String, Integer>> entries = map.entrySet();// Map.Entry<K, V> Set<E> } }
-
jdk 7类型推断,省略实例化时的泛型声明
LinkedList<Integer> list = new LinkedList<>(); Map<String,Integer> map = new HashMap<>();
- 自定义泛型结构:泛型类、泛型接口和泛型方法
private interface A<T> { T m(T data); } private class B<E, T> implements A<T> { B data; @Override public T m(T data) { return data; } }
- 如果定义了泛型,实例化时没有指明类的泛型,则认为此泛型类型为Object
List list = new LinkedList(); list.add(123); list.add("123");
- 使用了泛型时的继承与实现关系
private static class D implements A<String> {// D不是泛型类(不保留父类泛型) public <K> void print(K k) {// 泛型方法 System.out.println("K = " + k); } } private static class G extends C { // 擦除父类泛型,此时等价于private static class G extends C<Object,Object> } private static class E<R,T,F> extends C<R,T>{ // 全部保留父类泛型 } private static class F<T> extends C<String,T> { // 部分保留父类泛型 }
- 尽管在编译时List<String>和List<Integer>是两种不同的类型,但在运行时只有一个List被加载到了JVM中
ArrayList<Integer> list = new ArrayList<>(); ArrayList<Object> list1 = new ArrayList<>(); // list1 = list;// 报错,原因:ArrayList<Object>不是ArrayList<Integer>的子类
- 静态方法和静态变量无法使用泛型(泛型只有在实例化时才能确定其具体类型,而静态方法和静态变量随着类的加载而加载),但是可以定义静态泛型方法
public static <K> void print(K k) { System.out.println("K = " + k); }
- 异常类不能声明为泛型类;try-catch中不能catch泛型类
- 声明泛型类数组
T[] att = (T[]) new Object[10]; transient Object[] elementData; // 如ArrayList源码
- 泛型方法
public T m(T data) {// 非泛型方法 T[] att = (T[]) new Object[10]; return data; } public <K> void print(K k) {// 泛型方法 System.out.println("K = " + k); }
- 泛型通配符?
- ? extends XXX:必须是XXX或XXX的子类,例如List<? extends Number>可以是List<Integer>或者List<Double>或者List<Number>等
- ? super XXX:必须是XXX或XXX的父类,例如List<? super String> 可以是List<String>或者List<CharSequence>或者List<Object>
- List<? extends Number> list必须用Number接收list元素 List<? super String>list必须用Object接收列表元素 List<?>list只能向列表添加null元素,取出的元素只能用Object接收
@Test
public void test3() {
List<Integer> intList = Arrays.asList(1, 4, 2);
List<String> strList = Arrays.asList("AA", "BB");
List<Double> doubList = Arrays.asList(3.14, 2.7128);
List<?> list33 = new LinkedList<>();
list33.add(null);// 只能放null
Object o = list33.get(0);// 取出来是Object类型
System.out.println("list33 = " + list33);
List<?> list3 = intList;
printList(list3);
list3 = strList;
printList(list3);
printNumList(intList);
printNumList(doubList);
List<CharSequence> sequenceList = Arrays.asList("abc", "def");
printCharSeqList(sequenceList);
}
public void printList(List<?> list) {// 无条件限制的通配符
if (list.size() > 0) System.out.println("list.get(0) = " + list.get(0));
System.out.println("list = " + list);
}
// 有条件限制的通配符
public void printNumList(List<? extends Number> list) {
if (list.size() > 0) System.out.println("list.get(0) = " + list.get(0));
System.out.println("number list = " + list);
}
public void printCharSeqList(List<? super String> list) {
if (list.size() > 0) System.out.println("list.get(0) = " + list.get(0));
System.out.println("CharSeq list = " + list);
}