• 黑马程序员JAVA基础Java 集合之泛型


      所谓泛型就是允许在定义类、接口时指定类型形参,这个类型形参将在声明变量、创建对象时确定。增加了泛型支持后的集合,完全可以记住集合中元素的类型,并可以在编译时检查集合中元素的类型。即解决一些安全问题;同时还可以让代码变得更加简洁。

      

    一.使用泛型 

      泛型的格式:通过<>来定义要操作的引用数据类型

     1 public class GenericDemo {
     2     public static void main(String[] args)
     3     {
     4 //        创建一个只能保存字符串的List 集合
     5         List<String> strList = new ArrayList<String>() ;
     6         strList.add("Generic") ; 
     7 //        如果存放其他对象这回出现编译错误。
     8         System.out.println(strList);
     9     }
    10 }

       使用泛型的好处:

        1、将运行时期出现的ClassCastExcpetion , 转移到了编译时期。方便于程序员解决问题,让运行时期问题减少。

        2、避免了强制转换的麻烦。

      如下代码: 

     1 class StringDemo
     2 {
     3     String name ; 
     4     public StringDemo(String name )
     5     {
     6         this.name = name ; 
     7     }
     8 }
     9 public class GenericDemo {
    10     public static void main(String[] args)
    11     {
    12         List list = new ArrayList() ;  
    13         list.add(new StringDemo("烦烦烦烦烦01")) ; 
    14         list.add(new StringDemo("烦烦烦烦烦02")) ; 
    15         list.add(new StringDemo("烦烦烦烦烦03")) ; 
    16         list.add(new StringDemo("烦烦烦烦烦04")) ; 
    17         
    18         list.add(1000) ; 
    19         MyIterator(list) ; 
    20     }
    21 //    定义遍历方法:
    22     public static void MyIterator(List list)
    23     {
    24         Iterator it = list.iterator() ; 
    25         while (it.hasNext() )
    26         {
    27             StringDemo s = (StringDemo) it.next() ; 
    28             System.out.println(s.name);
    29         }
    30     }
    31 }
    }

      在调用MyIterator(List list) 方法时会发生ClassCastException 异常。而且在编译时是不会有任何提示,只有运行时会出现,所以使的程序存在安全隐患。

      如果使用泛型则会在编译时提示错误,而且在遍历时不需要强制转换。如: 

     1 class StringDemo
     2 {
     3     String name ; 
     4     public StringDemo(String name )
     5     {
     6         this.name = name ; 
     7     }
     8 }
     9 public class GenericDemo {
    10     public static void main(String[] args)
    11     {
    12         List<StringDemo> list = new ArrayList<StringDemo>() ;  
    13         list.add(new StringDemo("烦烦烦烦烦01")) ; 
    14         list.add(new StringDemo("烦烦烦烦烦02")) ; 
    15         list.add(new StringDemo("烦烦烦烦烦03")) ; 
    16         list.add(new StringDemo("烦烦烦烦烦04")) ; 
    17         
    18 //        下面一行代码在编译时会出错:
    19         list.add(1000) ; 
    20         MyIterator(list) ; 
    21     }
    22 //    定义遍历方法:
    23     public static void MyIterator(List list)
    24     {
    25         Iterator<StringDemo> it = list.iterator() ; 
    26         while (it.hasNext() )
    27         {   
    28             System.out.println( it.next().name);
    29         }
    30     }
    31 }

      注意:在使用Java提供的对象时,什么时候写泛型呢?

      只要见到<> (<>就是用来接收类型的。),就要定义泛型。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

    二.了解泛型

      ArrayList<E> 类定义和ArrayList<Integer> 类引用中涉及的术语:

      > 整个称为ArrayList<E> 泛型类型。

      > ArrayList<E> 中的E称为类型变量或类型参数。

      > 整个ArrayList<Integer> 称为参数化的类型。

      > ArrayList<Integer> 中的Integer 称为类型参数的实例或实际类型参数。

      > ArrayList<Integer> 中的<> 念着typeof

      > ArrayList 称为原始类型

      参数化类型不考虑类型参数的继承:

      > Vector<String> v = new Vector<Object>() ; //错误

      > Vector<Object> v = new Vector<String>() ; //也错误

      创建数组实例时,数组的元素不能使用参数化的类型:

      > Vector<Integer> vectorList[] = new Vector<Integer>[10] ; //错误

    三.定义泛型类

      除了Java提供了一些类增加了泛型支持外,我们可以定义泛型支持的类。那么在什么时候定义泛型类呢?

      当类中操作的引用数据类型不确定时可以定义泛型类。

      格式如下:

    class Tools<T>
    {
    }

      具体操作:

     1 //定义一个工具类Tools
     2 //因为不知道要操作的类型是什么所增加泛型支持
     3 class Tools<T>
     4 {
     5 //    包含输出函数:
     6     public void sop(T t)
     7     {
     8         System.out.println("sop:"+t);
     9     } 
    10 }
    11 //定义一个Books 类
    12 class Books
    13 {
    14     private String name ;
    15     public Books(String name)
    16     {
    17         this.name = name  ; 
    18     } 
    19 //    重写toString 方法
    20     public String toString()
    21     {
    22         return "name = " + name ;  
    23     }
    24 }
    25 public class GenericText 
    26 {
    27     public static void main(String[] args)
    28     { 
    29     //    创建一个Tools 实例tool ,定义 tool 要操作的数据类型为Books 
    30         Tools<Books>  tool = new Tools<Books>() ;  
    31     //    tool 可以操作 Books 类型,还可以操作Integer 类型和String类型。
    32         tool.sop(new Books("诛仙")); 
    33     }
    34 }

       定义一个Tools 类 用来完成打印操作,但是应为不知道要操作的数据类型是什么,所以可以定义成泛型类。

     三.泛型方法

      泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,

    那么可以将泛型定义在方法上。

      定义泛型方法格式如下:

            public <T> void show(T t) 注意:<>放在修饰符后面,返回值前面
            {
            }

      具体操作如下:

     1 //定义一个工具类Tools
     2 //因为不知道要操作的类型是什么所增加泛型支持
     3 class Tools<T>
     4 {
     5 //    包含输出函数:
     6     public void sop(T t)
     7     {
     8         System.out.println("sop:"+t);
     9     } 
    10 //    定义的泛型方法:
    11     public <T> void show (T t)
    12     {
    13         System.out.println("show:"+t);
    14     }
    15 }
    16 //定义一个Books 类
    17 class Books
    18 {
    19     private String name ;
    20     public Books(String name)
    21     {
    22         this.name = name  ; 
    23     } 
    24 //    重写toString 方法
    25     public String toString()
    26     {
    27         return "name = " + name ;  
    28     }
    29 }
    30 public class GenericText 
    31 {
    32     public static void main(String[] args)
    33     { 
    34     //    创建一个Tools 实例tool ,定义 tool 要操作的数据类型为Books 
    35         Tools<Books>  tool = new Tools<Books>() ;  
    36     //    tool 可以操作 Books 类型,还可以操作Integer 类型和String类型。
    37         tool.sop(new Books("诛仙")); 
    38         tool.show(new Books("诛仙")) ; 
    39 //        下面的方法编译时会报错》、:
    40         tool.sop(1000) ;
    41         tool.sop("String") ;
    42         
    43 //        但下面却不会报错,并且正常运行。
    44         tool.show(1000) ; 
    45         tool.show("String") ;
    46     }
    47 }

       通过上面的代码,可以知道泛型类和泛型方法可以同时定义,且不冲突。但是也有特殊情况:静态方法不可以访问定义类上的泛型,如:

            class Tools<T>
            {
                public static void method(T t)
                {
                }
            }
            上面的书写是错误的,

      如果静态方法操作的引用数据类型不确定,可将泛型定义在方法上:

            class Tools<T>
            {
                public static <T> void method(T t)
                {
                }
            }

      

      

    四.泛型限定和通配符

      4.1 通配符

      类型通配符是一个问号(?):问号作为类型实参传给List 集合写作:List<?>。

     1 //定义一个Books 类
     2 class Books
     3 {
     4     private String name ;
     5     public Books(String name)
     6     {
     7         this.name = name  ; 
     8     } 
     9 //    重写toString 方法
    10     public String toString()
    11     {
    12         return "name = " + name ;  
    13     }
    14 }
    15 public class GenericText 
    16 {
    17     public static void main(String[] args)
    18     {
    19 //        创建一个只能存储 Books 类型元素的 List 集合。
    20         List<Books> bookList = new ArrayList<Books>() ;  
    21         bookList.add(new Books("诛仙")) ;
    22         bookList.add(new Books("笑傲江湖")) ; 
    23         
    24 //        创建一个只能存储String 类型元素的List 集合
    25         List<String> strList = new ArrayList<String>() ;
    26         strList.add("Generic001") ;
    27         strList.add("Generic002") ;
    28         
    29         MyIterator(strList) ; 
    30         MyIterator(bookList) ;
    31         
    32     }
    33 //    定义个遍历List 集合的方法。
    34     public static void MyIterator(List<?>  strList)
    35     {
    36         Iterator<?> it = strList.iterator() ;
    37         while(it.hasNext())
    38         {
    39             System.out.println(it.next());
    40         }
    41     }
    42 }

      在 MyIterator 方法中使用了类型通配符 ? ,好处是只写一个 遍历方法便可操作List 集合的遍历,缺点是不能调用元素中的特定方法。

       

      4.2 泛型限定:

        1、 ? extends E : 可以接收E类型或者E的子类型。上限定。

        2、? super E : 可以接收E类型或者E的父类型。下限定。

        

     1 class Books
     2 {
     3     String name ;
     4     public Books(String name)
     5     {
     6         this.name = name  ; 
     7     }  
     8     public String toString()
     9     {
    10         return "name:" + name ; 
    11     }
    12 }
    13 class ComicBooks extends Books
    14 { 
    15     public ComicBooks(String name) {
    16         super(name); 
    17     } 
    18 }
    19 class Person_1 
    20 {
    21     String name ; 
    22     public Person_1 (String name)
    23     {
    24         this.name = name ;
    25     }
    26 }
    27 public class GenericTreeSet {
    28     
    29     public static void main(String[] args)
    30     {
    31 //        定义 TreeSet 集合 ,并且里面只存储ComicBooks类型元素,切按照自已的比较规则排序
    32         TreeSet<ComicBooks> bookTree = new TreeSet<ComicBooks>(new MyComparable()) ;
    33         
    34         bookTree.add(new ComicBooks("aaaaaa")) ;
    35         bookTree.add(new ComicBooks("aaa3gfaaa")) ;
    36         bookTree.add(new ComicBooks("afdfef")) ;
    37         bookTree.add(new ComicBooks("asdffefq")) ;
    38 //        调用
    39         MyIterator(bookTree) ; 
    40         
    41 //        下面代码编译会出现异常
    42         TreeSet<Person_1> p = new TreeSet<Person_1>(new MyComparable()) ;
    43     }
    44 //    定义遍历方法:只能操作Books 类型或者 Books的子类型
    45     public static void MyIterator(TreeSet<? extends Books> bookTree)
    46     {
    47         Iterator<? extends Books> it =  bookTree.iterator()  ;
    48         while(it.hasNext())
    49         {
    50             System.out.println(it.next().toString());
    51         }
    52     }
    53 }
    54 //定义比较器 :按倒序排序且该比较器只适用于 Books 类型或者 Books的子类型
    55 class MyComparable implements Comparator<Books>
    56 { 
    57     public int compare(Books o1 , Books o2)
    58     {  
    59         return o2.name.compareTo(o1.name);
    60     } 
    61 }

      所以,当我们定义的某些方法只作用与某些类与其子类时,可以通过泛型限定来实现。

  • 相关阅读:
    开篇词The Start以及[Vjudge][HDU2242]空调教室
    [故地重游][NOIP2019]格雷码
    关于非触
    致诸君
    三角形的概率
    [HDU5970] 最大公约数
    [51Nod1534] 棋子游戏
    [TJOI2018] 数学计算
    [CF938D] Buy a Ticket
    [HDU4143] A Simple Problem
  • 原文地址:https://www.cnblogs.com/jbelial/p/2990935.html
Copyright © 2020-2023  润新知