跳转至

泛型

一、概念

所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如继承或实现这个接口,用这个类型声明变量,创建对象时)确定(即传入实际的类型参数,也称为类型实参)

二、没有泛型会出现的问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.ArrayList;

public class GenericTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();

        list.add(78);
        list.add(63);
        list.add(43);
        list.add(87);

        // 不使用泛型的问题
        // 1. 类型不安全
        list.add("A");

        for (Object score : list) {
            // 2. 强转时出现ClassCastException
            int stuScore = (Integer) score;
            System.out.println(stuScore);
        }
    }
}

三、使用泛型

泛型的类型必须是类,不能是基本数据类型。如果实例化时没有指明泛型的类型,默认类型为java.lang.Object类型

1. 集合中使用泛型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.util.ArrayList;
import java.util.Iterator;

public class GenericTest {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        // 类型推断,jdk7中引入
        // ArrayList<Integer> list = new ArrayList<>();

        list.add(78);
        list.add(63);
        list.add(43);
        list.add(87);

        // 在编译时就会进行类型检查,保证数据的安全
        // list.add("A");

        for (Integer score : list) {
            // 省去了强转操作
            int stuScore = score;
            System.out.println(stuScore);
        }

        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

2. Map中使用泛型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class GenericTest {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Tom", 78);
        map.put("Jerry", 81);
        // 泛型嵌套
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            System.out.println(next.getKey() + "-->" + next.getValue());
        }
        // Tom-->78
        // Jerry-->81
    }
}

四、自定义泛型结构

1. 泛型类、泛型接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class GenericTest {
    public static void main(String[] args) {

        // 如果定义了泛型类,实例化没有指明泛型类,默认为此泛型类型为Object类型
        // Order order = new Order();

        // 如果定义了类是带泛型的,建议在实例化时要指明类的泛型
        Order<String> order1 = new Order<>("A", 1001, "a:1001");
        order1.setOrderT("a:1001");

        // 由于子类在继承带泛型的父类是,指明了泛型类型,则实例化子类对象时,不需要指明泛型
        SubOrder order2 = new SubOrder();
        order2.setOrderT(123);

        ChildrenOrder<Object> order3 = new ChildrenOrder<>();
        order3.setOrderT("BBB");
    }
}


class Order<T> {
    String orderName;
    int orderId;
    // 类的内部结构就可以使用类的泛型
    T orderT;

    public T getOrderT() {
        return orderT;
    }

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }


    public Order() {
    }


    public Order(String orderName, int orderId, T orderT) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }
}


class SubOrder extends Order<Integer> {

}


class ChildrenOrder<T> extends Order<T> {

}

2. 泛型方法

在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.ArrayList;
import java.util.List;

public class GenericTest {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        Integer[] arr = new Integer[]{1, 2, 3, 4};
        List<Integer> list = myClass.method(arr);
        System.out.println(list);
    }
}


class MyClass {
    // 泛型方法可以声明为静态的,因为泛型参数是在调用方法时确定的,并非在实例化时确定
    public <E> List<E> method(E[] arr) {
        ArrayList<E> list = new ArrayList<>();
        for (E e : arr) {
            list.add(e);
        }
        return list;
    }
}

五、泛型在继承方面的体现

类A是类B的父类,G<A>G<B>二者不具备父子类关系,二者是并列关系;A<G>B<G>的父类。

六、通配符的使用

类A是类B的父类,G<A>G<B>是没有关系的,二者共同的父类是G<?>

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GenericTest {
    public static void main(String[] args) {
        List<Object> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        list1.add(1);
        list2.add("A");
        List<?> list = null;

        list = list1;
        list = list2;

        show(list1);
        show(list2);
        // 添加
        // 对于List<?> 不能像其内部添加数据。
        // 除了null之外
        // list.add("2");
        list.add(null);
        show(list2);

        // 读取 允许读取数据,读取的数据类型为Object
        Object o = list.get(0);
        System.out.println(o);
    }

    public static void show(List<?> list) {
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
}

有限制条件的通配符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// ? extends A:  G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类
// ? super A: G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类

import java.util.Iterator;
import java.util.List;

public class GenericTest {
    public static void main(String[] args) {
        List<? extends Person> list1 = null;
        List<? super Person> list2 = null;

        List<Student> list3 = null;
        List<Person> list4 = null;
        List<Object> list5 = null;

        list1 = list3;
        list1 = list4;
        // list1 = list5;  // 不允许


        // list2 = list3;  // 不允许
        list2 = list4;
        list2 = list5;
    }

    public static void show(List<?> list) {
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }
}


class Person {

}

class Student extends Person {

}