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 }
时间: 2024-12-29 16:58:45

java之泛型理解(高效java之泛型)的相关文章

谈谈对Java平台的理解

从我第一次接触Java的时候,老师就说"Write once,run anywhere",这句话虽然听起来有一点太过于形式主义,但是也突出了它的特点.那么,现在的我们应该总结一下和思考一下,自己对于Java平台的理解. Java本身是一种面向对象的语言,最显著的两个特性有两个方面: ①.书写一次,到处运行,具有跨平台的能力: ②.具有垃圾收集(GC,Garbage Collection)功能,Java通过垃圾收集器(GC)回收分配内存,大部分情况下,程序员不需要自己担心内存的分配和回收

谈谈你对java平台的理解?

问题:谈谈你对java平台的理解?java是解释执行,这句话对吗? 典型回答:java本身是一种面向对象的语言,具有很好的跨平台的能力,能够做到"write once ,run anywhere".另外就是GC机制,java通过垃圾回收器回收分配内存,程序员无需自己操心内寸的回收问题. 我们日常会接触到jre和jdk.jre是java运行环境,包含了jvm和java类库等.jdk则是在jre的基础上提供了更多的工具,比如编译器,和一些诊断工具等. java是解释执行,这句话不是很准确.

Java核心-01谈谈你对Java平台的理解

今天我要问你的问题是,谈谈你对 Java 平台的理解?“Java 是解释执行”,这句话正确吗? 典型回答 Java本身是一种面向对象的语言,最显著的特性有两个.一是所谓的“书写一次,到处运行”,能够非常容易获得跨平台能力:另一个就是垃圾收集,Java通过垃圾收集器回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收. 我们日常接触到 JRE( Java Runtime Environment) 或者 JDK( Java Development Kit).JRE 也就是 Java 运行

Java String的理解

Java String的理解 在Java中String是一个比较特殊的对象---不可继承,不可变,直接赋值创建 不可继承,不可变 String 类型被标final关键字修饰,所以不可继承 public final class String implements java.io.Serializable, Comparable<String>, CharSequence { // .... } Sting类中提供了一个final修饰的字符数组,用于存储Sting类型的值,所以一旦初始化则不能修改

Java反射的理解(六)-- 通过反射了解集合泛型的本质

Java反射的理解(六)-- 通过反射了解集合泛型的本质 上述写了那么多,我们可能会有个疑问,为什么要用反射,步骤比我们常规的加载类操作复杂多了,别急,这个问题我最后才解答,我们先来了解集合泛型的本质. 直接上代码: import java.lang.reflect.Method; import java.util.ArrayList; public class MethodDemo4 { public static void main(String[] args) { ArrayList li

java从基础知识(八)泛型

1.什么是泛型? 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引入泛型的好处是安全简单. 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的.对于强制类型转换错

(转)1.21 Java总结篇系列:Java泛型

一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(String[] args) { 4 List list = new ArrayList(); 5 list.add("qqyumidi"); 6 list.add("corn"); 7 list.add(100); 8 9 for (int i = 0; i < lis

java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题

java泛型(二).泛型的内部原理:类型擦除以及类型擦除带来的问题 参考:java核心技术 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首要前提是理解类型擦出(type erasure). Java中的泛型基本上都是在编译器这个层次来实现的.在生成的Java字节码中是不包含泛型中的类型信息的.使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉.这个过程就称为类型

Java泛型通配符学习 —— Java Generic&#39;s Wildcards

Java Generic's wildcards is a mechanism in Java Generics aimed at making it possible to cast a collection of a certain class, e.g A, to a collection of a subclass or superclass of A. This text explains how. 理解:Java的泛型通配符机制旨在实现集合的类型转换.例如集合A,转换为A的子类集合或