泛型(generic):声明中具有一个或多个类型参数
原始类型(raw type):不带任何实际类型参数的泛型名称
格式: <code>类或接口的名称</code> <code><</code> <code>对应于泛型形式类型参数的实际参数</code> <code>></code> 如 <code>list<string></code> 就是对应于<code>list<e></code>的实际参数为<code>string</code>的参数化类型 如与<code>list<e></code>对应的原始类型是<code>list</code>
优点:
在编译时发现插入类型的错误(越早发现错误越好,编译时发现好于运行时发现)
不再需要手工转换类型
<code>list</code>和<code>list<object></code>之间的区别? <code>list</code>逃避了泛型检查,<code>list<object></code>则是告知编译器,它能够持有任意类型的对象
无限制的通配符类型:
使用泛型,但不确定或者不关心实际的类型参数,可以用一个问号代替。如list<?>
学习链接: <a href="https://docs.oracle.com/javase/tutorial/java/generics/erasure.html">1.https://docs.oracle.com/javase/tutorial/java/generics/erasure.html</a> <a href="http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java">2.http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java</a>
下面通过一个小demo说明类型擦除
运行结果:
一般不在代码中使用原始类型,除了两种例外情况(都是因为泛型信息在运行时会被擦除):
1.在类文字(class literals)中
<code>如: list.class,string[].class,int.class都合法 list<string>.class,list<string>.class都不合法</code>
2.instanceof
下面的表格是泛型相关的术语:
下面这张图很好的介绍了无限制通配符和其他泛型符号之间的关系:
始终在尽可能小的范围内使用suppresswarnings注解
java源码中的arraylist类中有个toarray方法,其中就有强转的警告:
最好是将范围进一步缩小。将注解由整个方法到局部的变量声明上去。
数组是协变的(covariant),泛型则是不可变的
数组是具体化的(reified),在运行时才知道并检查它们的元素类型约束。而泛型通过擦除来实现的。泛型只在编译时强化类型信息,并在运行时擦除它们的元素类型信息。擦除就是使泛型可以与没有使用泛型的代码可以互用。
数组和泛型不能很好地混合使用。可用列表代替数组。
总结:数组是协变且可具体化的,泛型是不可变的且可被擦除的。-->数组提供了运行时类型安全而编译时类型不安全。而泛型反之。
泛型相比于object的优点:
不需要强制类型转换
编译时类型安全
前面曾鼓励优先使用列表而不是数组。并不意味着所有的泛型中都要使用列表。况且java并不是生来就支持列表的。
每个类型都是它自身的子类型。
方法可以考虑泛型化,特别是静态工具方法。
泛型方法语法:
方法修饰语 泛型 返回值 方法名() <code>public static <t> t foo(t args);</code>
泛型单例工厂:
递归类型限制:
通过某个包含该类型参数本身的表达式来限制类型参数
参数化类型是不可变的。
从上面的demo中我们知道,java中提供了<code>有限制的通配符类型</code>来提高api的灵活性。
如 collection<? extends e> collection<? super e>
一般在表示生产者或消费者的输入参数上使用通配符类型。
pecs:producer-extends consumer-super
原文地址:http://www.cnblogs.com/johntsai/p/5344733.html