zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    一步一步学grails:7 MVC
    虚拟机安装CentOS7
    虚拟机安装windows sever2008
    微信console
    centOS7常用操作命令
    lr事务
    2.0通信之调用ADO.NET Data Services(数据服务)
    Silverlight应用程序中如何获取ASP.NET页面参数
    2.0网页之可脚本化, 与DOM的交互, 与JavaScript的交互
    2.0Tip/Trick之MessageBox, Popup, 循环的几种实现方法, 动态变换主题, 本地化(多语言), 响应鼠标双击事件
  • 原文地址:https://www.cnblogs.com/niujifei/p/12208282.html
Copyright © 2011-2022 走看看