zoukankan      html  css  js  c++  java
  • java之泛型理解(高效java之泛型)

     1  * 泛型-->类或者接口的声明中拥有一个或多个类型参数时,称为泛型类/泛型接口,简称泛型 
     2  * 泛型在安全性和表述性上都比原生态类型更具有优势
     3  * 泛型是不可变的,无法向数组一样形成协变关系 
     4  * (Sub extends Super,同时可支持Sub[] extends Super[]) 
     5  * (Sub extends Super,不支持List<Sub> extends List<Super>) 
     6  * 泛型在编译时检查其元素类型信息,而在运行期舍弃其元素类型信息
     7  *  每个类都是自身的子类型和超类型
     8  * T 形式类型参数 
     9  * E 集合中的形式类型参数 
    10  * K Map中的键形式参数 
    11  * V Map中的值形式参数 
    12  * ? 任意匹配的配型参数 <? extends E>/<? super E>
    13  * 有限的通配符形式参数(PECS)
    14  * 
    15  * Class<T> 泛型 
    16  * Class<String> 参数化的类型 
    17  * Class 原生态类型(删除了所有的泛型信息) 
    18  * Class<?> 无限制的通配符类型
    19  * Class<? extends E> 有限制的通配符类型
    20  *  <T> 形式类型参数 
    21  *  <String> 实际类型参数
    22  * 
    23  * static <E> E get(E e) 泛型方法
    24  *  (<E> 称为类型参数列表,即在调用方法之前告诉编译器,此方法中的类型都是什么类型)
    25  * 编译器使用泛型方法可通过类型推导,推导出类型参数列表的类型

    测试代码

      1 package com.undergrowth.lang;
      2 
      3 import java.io.Serializable;
      4 import java.util.Arrays;
      5 import java.util.Collection;
      6 import java.util.Collections;
      7 import java.util.List;
      8 import java.util.concurrent.CopyOnWriteArrayList;
      9 
     10 import org.junit.Test;
     11 
     12 /**
     13  * 泛型学习测试代码
     14  * 
     15  * 泛型-->类或者接口的声明中拥有一个或多个类型参数时,称为泛型类/泛型接口,简称泛型 
     16  * 泛型在安全性和表述性上都比原生态类型更具有优势
     17  * 泛型是不可变的,无法向数组一样形成协变关系 
     18  * (Sub extends Super,同时可支持Sub[] extends Super[]) 
     19  * (Sub extends Super,不支持List<Sub> extends List<Super>) 
     20  * 泛型在编译时检查其元素类型信息,而在运行期舍弃其元素类型信息
     21  *  每个类都是自身的子类型和超类型
     22  * T 形式类型参数 
     23  * E 集合中的形式类型参数 
     24  * K Map中的键形式参数 
     25  * V Map中的值形式参数 
     26  * ? 任意匹配的配型参数 <? extends E>/<? super E>
     27  * 有限的通配符形式参数(PECS)
     28  * 
     29  * Class<T> 泛型 
     30  * Class<String> 参数化的类型 
     31  * Class 原生态类型(删除了所有的泛型信息) 
     32  * Class<?> 无限制的通配符类型
     33  * Class<? extends E> 有限制的通配符类型
     34  *  <T> 形式类型参数 
     35  *  <String> 实际类型参数
     36  * 
     37  * static <E> E get(E e) 泛型方法
     38  *  (<E> 称为类型参数列表,即在调用方法之前告诉编译器,此方法中的类型都是什么类型)
     39  * 编译器使用泛型方法可通过类型推导,推导出类型参数列表的类型
     40  * 
     41  * 此内容主要涉及泛型类和泛型方法,测试用例-->testGenericeClass
     42  * 泛型集合-->testGeneCollection
     43  * 有限的通配符使用-->testBoundWildType
     44  * 泛型编译器维护类型信息,运行时舍弃-->testEraseGenericsInfo
     45  * 
     46  * @author Administrator
     47  * 
     48  */
     49 public class GenericsLearn {
     50 
     51     /**
     52      * 测试泛型类和方法
     53      */
     54     @Test
     55     public void testGenericeClass() {
     56         GenericeClass<String> gClass1 = new GenericeClass<String>("测试泛型类参数");
     57         System.out.println(gClass1);
     58         System.out.println(gClass1.getAddSome("泛型方法"));
     59         System.out.println(gClass1.getAddSome(123));
     60     }
     61 
     62     /**
     63      * 泛型测试类
     64      * 
     65      * @author Administrator
     66      * 
     67      * @param <T>
     68      */
     69     private static class GenericeClass<T> {
     70         private final T t;
     71 
     72         public GenericeClass(T t) {
     73             super();
     74             this.t = t;
     75         }
     76 
     77         /**
     78          * 获取对象后 添加附加信息
     79          * 
     80          * @param t
     81          * @return
     82          */
     83         public <E> E getAddSome(E t) {
     84             if (t instanceof String) {
     85                 // 因为在进入此方法时 已做了类型判断 使用注解消除非受检警告
     86                 @SuppressWarnings("unchecked")
     87                 E t1 = (E) (String.valueOf(t) + ",附加泛型防范新消息");
     88                 return t1;
     89             }
     90             return t;
     91         }
     92 
     93         public void iterator(Iterable<? extends T> src) {
     94             for (T t : src) {
     95                 System.out.println(t);
     96             }
     97         }
     98 
     99         @Override
    100         public String toString() {
    101             return "GenericeClass [t=" + t + "]";
    102         }
    103 
    104     }
    105 
    106     /**
    107      * 测试泛型集合
    108      */
    109     @Test
    110     public void testGeneCollection() {
    111         Collection<String> collection = createCollection("123");
    112         /*
    113          * for (Iterator<String> iterator = collection.iterator();
    114          * iterator.hasNext();) { String string = (String) iterator.next();
    115          * System.out.println(string); }
    116          */
    117         iterator(collection);
    118     }
    119 
    120     /**
    121      * 创建测试集合
    122      * 
    123      * @return
    124      */
    125     private <E> Collection<E> createCollection(E t) {
    126         // TODO Auto-generated method stub
    127         Collection<E> collection = Collections.emptyList();
    128         if (t instanceof String) {
    129             collection = new CopyOnWriteArrayList<E>();
    130             // 已经进行类类型检查 所以转换时没有问题的 每个类都是自身的子类型和超类型
    131             @SuppressWarnings("unchecked")
    132             Collection<? extends E> initData = (Collection<? extends E>) Arrays
    133                     .asList(new String[] { "测试集合1", "测试集合2", "测试集合3" });
    134             collection.addAll(initData);
    135         }
    136         return collection;
    137     }
    138 
    139     /**
    140      * 创建Number集合
    141      * 此方法不推荐使用 这里只是测试使用  
    142      * @return
    143      */
    144     @Deprecated
    145     private <E> Collection<E> createNumber() {
    146         Collection<E> collection = new CopyOnWriteArrayList<E>();
    147         @SuppressWarnings("unchecked")
    148         Collection<? extends E> initData = (Collection<? extends E>) Arrays
    149                 .asList(new Number[] { 123.2, Integer.MAX_VALUE, 789 });
    150         // System.out.println(initData.getClass().getName());
    151         collection.addAll(initData);
    152         return collection;
    153     }
    154 
    155     /**
    156      * 迭代实现了Iterable接口的可迭代子类
    157      * 
    158      * @param src
    159      */
    160     public <E> void iterator(Iterable<E> src) {
    161         for (E e : src) { // 内部通过迭代器来遍历元素
    162             System.out.println(e);
    163         }
    164     }
    165 
    166     /**
    167      * 测试有限的通配符类型 每个类都是自身的子类型和超类型
    168      *  PECS原则-->producer-extends,consumer-super
    169      */
    170     @Test
    171     public void testBoundWildType() {
    172         GenericeClass<Number> gClass1 = new GenericeClass<Number>(123456);
    173         System.out.println(gClass1);
    174         System.out.println(gClass1.getAddSome("123456"));
    175         // 创建Number数组
    176         Collection<Number> collection = createNumber();
    177         iterator(collection);
    178         // 使用GenericeClass的迭代方法进行迭代 每个类都是自身的子类型和超类型
    179         System.out
    180                 .println("使用有限的通配符进行迭代 形式为:Iterable<? extends T>  实际为:Iterable<Number extends Number> 每个类都是自身的子类型和超类型");
    181         gClass1.iterator(collection);
    182         Collection<Integer> collection2 = createNumber();
    183         // 使用foreach进行迭代
    184         System.out.println("使用foreach进行迭代");
    185         iterator(collection2);
    186         // 使用有限的通配符进行迭代
    187         System.out
    188                 .println("使用有限的通配符进行迭代 形式为:Iterable<? extends T>  实际为:Iterable<Integer extends Number>");
    189         gClass1.iterator(collection2);
    190         System.out.println("进行字符串集合的foreach迭代");
    191         Collection<String> collection3 = createNumber();
    192         iterator(collection3);
    193         System.out.println("如果使用collection3.add(123)方法,泛型的安全性检查就会得到体现,编译器会报错");
    194         // collection3.add(123);
    195         System.out
    196                 .println("如果调用gClass1.iterator(collection3)方法,就会有问题,因为形式为:Iterable<? extends T> 实际为:Iterable<String extends Number>");
    197         // gClass1.iterator(collection3);
    198         System.out.println("获取Serializable集合");
    199         Collection<Serializable> collection4 = createNumber();
    200         iterator(collection4);
    201         System.out
    202                 .println("之前一直有个疑惑,为什么Collection<Number>、Collection<Integer>、Collection<String>、Collection<Serializable>、Collection<List>调用的时候 能够返回相应的集合,"
    203                         + "因为很明显 在createNumber方法中创建的是Number的List<Number>集合 我们有知道泛型是不可协变的 为什么会成功呢 ");
    204         System.out
    205                 .println("因为泛型在编译器检查其类型信息(所以当定义Collection<Serializable> collection4 = createNumber();的时候 调用createNumber,而此方法只会进行类型检查,createNumber为泛型方法,所以编译时是没有问题的),而在运行时丢弃其元素类型信息,并且强制类型转换是在运行期进行的,所以在(Collection<? extends E>)强制类型转换实际上是(Collection)List,所以运行期也没有问题,调试一下就知道了,害我想了1个多小时");
    206     }
    207 
    208     /**
    209      * 测试泛型只在编译器维护其类型信息 在运行期不会维护其元素的类型信息 
    210      * 下面代码会报错 java.lang.ClassCastException:
    211      * java.lang.Double cannot be cast to java.util.List
    212      */
    213     @Test
    214     public void testEraseGenericsInfo() {
    215         System.out.println("获取List集合");
    216         Collection<List> collection5 = createNumber();
    217         for (List list : collection5) {
    218             System.out.println(list.get(0));
    219             ;
    220         }
    221     }
    222     
    223     
    224     @Test
    225     public void testOther() {
    226         Integer integer = (int) 13.2;
    227         String aString = String.valueOf(13.2);
    228     }
    229 
    230 }
  • 相关阅读:
    使用BackgroundWorker组件进行异步操作编程《转》
    C#多线程控制进度条之长任务操作《转》
    模态进度条窗体实现<转>
    dev xtraReports使用《转》
    客户端IP
    WebService获取服务端硬件信息和客户端IP,MAC,浏览器信息,所在城市《转》
    c#多线程 Invoke方法的使用<转>
    C# windowform进度条《转》
    XtraReports 打印控件的简单使用《转》
    hdu Marriage Match II
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/java_generics.html
Copyright © 2011-2022 走看看