Java 之 泛型的其他知识

一、并不存在泛型类的 Class 对象

  1、Type<String> 和 Type<Integer> 的区别?

     通过泛型使得一个类型的功能增强了,好像扩展出好多子类一样。

     例如:ArrayList<E>,通过指定泛型,可以延伸出 ArrayList<String> 只能处理字符串类型的集合,ArrayList<Employee> 只能处理 Employee 员工类型的集合。但是,实际上,系统并没有为 ArrayList<String> 等生成新的 class 文件,而且也不会把 ArrayList<String> 当成新的类型处理。

    看下面的代码的打印结果是什么?

        ArrayList<Integer> list1 = new ArrayList<Integer>();
        ArrayList<String> list2 = new ArrayList<String>();
        System.out.println(list1.getClass());
        System.out.println(list2.getClass());
        System.out.println(list1.getClass() == list2.getClass()); //true

    可见,ArrayList<String> 不是 ArrayList<Object> 的子类,因为它们的运行时类型都是 ArrayList,因此不允许如下赋值操作。

ArrayList<Object> list = new ArrayList<String>();   //错误的

      这点和数组不同,因为数组要生成新的 Class 对象的,String[] 仍然是 Object[] 的子类,因此允许如下赋值操作。

Object[] arr = new String[5];

      但是数组这么处理也是有风险的,如下操作编译正确,但运行时会报 ArrayStoreException,所以请谨慎这样操作。

        Object[] arr = new String[5];
        arr[0] = 12;//因为12不是字符串对象

  2、instanceof 后面不支持泛型类

    由于系统中并不会真正生成泛型类,所以如下操作也都是不允许的:

1         ArrayList<String> list = new ArrayList<String>();
2        //编译错误,instanceof后面不能使用泛型类
3         if(list instanceof ArrayList<String>){
4             
5         }

  3、泛型与数组

     数组的元素类型不能包含类型变量或类型形参,除非是无上限的类型通配符。

 1     public static void main(String[] args) {
 2         List<?>[] arr = new List<?>[2];
 3         arr[0] = Arrays.asList("hello","java");
 4         arr[1] = Arrays.asList(1,2,3);
 5         for (List<?> list : arr) {
 6             for (Object object : list) {
 7                 System.out.println(object);
 8             }
 9         }
10     }

    只能声明这样的数组,但是不能创建这样的数组对象,以下代码编译错误:

ArrayList<String>[] array = new ArrayList<String>[5]; //编译错误

      以下代码也是错误的:

1 class MyClass<T>{
2     private T[] arr;
3 
4     public MyClass(int length) {
5         super();
6         this.arr = new T[length];                                        
7     }
8 }

  4、泛型与异常

    不能在 try-catch 中使用类型变量,也不能在 throws 后面使用类型变量。

二、泛型嵌套:从外到内分析

  案例:已知有省份 Provice 类型,有属性省份编号id和名称 name,有城市 City 类型,有属性城市编号id和名称 name,所属省份编号 pid.如果要存储如下信息到一个 Map 中,该如何指定泛型呢?其中 key为省份对象,value 为该省份对应的所有城市对象。

  

   分析:key 的类型为 Provice,而 value 要保存多个城市对象,因此是一个 List 或 Set,因此泛型实参为 City类型。如:TreeMap<Province,TreeSet<City>>。

  完整代码示例:

    Provice 类

 1 public class Province implements Comparable<Province>{
 2     private int id;
 3     private String name;
 4     public Province(int id, String name) {
 5         super();
 6         this.id = id;
 7         this.name = name;
 8     }
 9     public Province() {
10         super();
11     }
12     public int getId() {
13         return id;
14     }
15     public void setId(int id) {
16         this.id = id;
17     }
18     public String getName() {
19         return name;
20     }
21     public void setName(String name) {
22         this.name = name;
23     }
24     @Override
25     public String toString() {
26         return id + ":" + name;
27     }
28     @Override
29     public int compareTo(Province o) {
30         return this.id - o.id;
31     }
32 }

   City 类:

 1 public class City implements Comparable<City>{
 2     private int id;
 3     private String name;
 4     private int pid;
 5     public City(int id, String name, int pid) {
 6         super();
 7         this.id = id;
 8         this.name = name;
 9         this.pid = pid;
10     }
11     public City() {
12         super();
13     }
14     public int getId() {
15         return id;
16     }
17     public void setId(int id) {
18         this.id = id;
19     }
20     public String getName() {
21         return name;
22     }
23     public void setName(String name) {
24         this.name = name;
25     }
26     public int getPid() {
27         return pid;
28     }
29     public void setPid(int pid) {
30         this.pid = pid;
31     }
32     @Override
33     public String toString() {
34         return id + ":" + name;
35     }
36     @Override
37     public int compareTo(City o) {
38         return this.id - o.id;
39     }
40 }

  测试类:

 1 import java.util.Map.Entry;
 2 import java.util.Set;
 3 import java.util.TreeMap;
 4 import java.util.TreeSet;
 5 
 6 public class AreaManager {
 7     public static void main(String[] args) {
 8          //key为Province,value是一个TreeSet<City>
 9         TreeMap<Province,TreeSet<City>> map = new TreeMap<Province,TreeSet<City>>();
10                 
11         TreeSet<City> bj = new TreeSet<City>();
12         bj.add(new City(1,"北京市",1));
13         map.put(new Province(1,"北京市"), bj);
14         
15         TreeSet<City> hn = new TreeSet<City>();
16         hn.add(new City(1,"海口市",2));
17         hn.add(new City(2,"三亚市",2));
18         map.put(new Province(2,"海南省"), hn);
19         
20         TreeSet<City> zj = new TreeSet<City>();
21         zj.add(new City(1,"绍兴市",3));
22         zj.add(new City(2,"温州市",3));
23         zj.add(new City(3,"湖州市",3));
24         zj.add(new City(4,"嘉兴市",3));
25         zj.add(new City(5,"台州市",3));
26         zj.add(new City(6,"金华市",3));
27         zj.add(new City(7,"舟山市",3));
28         zj.add(new City(8,"衢州市",3));
29         zj.add(new City(9,"丽水市",3));
30         map.put(new Province(3,"浙江省"), zj);
31         //Map中实际存储的是一个个的Entry对象,所有的Entry就组成了一个Set集合
32 //而Entry类型的key是Province,value是TreeSet<City>
33         Set<Entry<Province, TreeSet<City>>> entrySet = map.entrySet();
34         for (Entry<Province, TreeSet<City>> entry : entrySet) {
35             Province key = entry.getKey();
36             System.out.println(key);
37             TreeSet<City> value = entry.getValue();
38             for (City city : value) {
39                 System.out.println("\t" + city);
40             }
41         }
42     }
43 }

猜你喜欢

转载自www.cnblogs.com/niujifei/p/12208282.html