• 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("	" + city);
    40             }
    41         }
    42     }
    43 }
  • 相关阅读:
    SharePoint 2010 User Profile Sync Service自动停止
    如何区别多个svchost.exe?
    Log Parser分析IIS log的一个简单例子
    Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
    Windows中右键点击文件夹, 结果找不到共享选项卡, 怎么办?
    介绍SOS中的SaveModule命令
    SharePoint中Draft版本的文档不会收到document added的Alert Email
    和我一起学Windows Workflow Foundation(1)创建和调试一个WF实例
    门户网站
    C#基础—— check、lock、using语句归纳
  • 原文地址:https://www.cnblogs.com/niujifei/p/12208282.html
Copyright © 2020-2023  润新知