之前因为博客被盗 此篇文章写在博客园了 但是后面又加了写泛型的东西 故还是放到此处
不过还是要感谢csdn的 webmaster@csdn.net 给它发邮件 不但账号找回了 被删的文章也找回 再次感谢CSDN的工作人员 谢谢
多说无益 一切尽在代码和注释中
/**
* 泛型学习测试代码
*
* 泛型-->类或者接口的声明中拥有一个或多个类型参数时,称为泛型类/泛型接口,简称泛型
* 泛型在安全性和表述性上都比原生态类型更具有优势
* 泛型是不可变的,无法向数组一样形成协变关系
* (Sub extends Super,同时可支持Sub[] extends Super[])
* (Sub extends Super,不支持List<Sub> extends List<Super>)
* 泛型在编译时检查其元素类型信息,而在运行期舍弃其元素类型信息
* 每个类都是自身的子类型和超类型
* T 形式类型参数
* E 集合中的形式类型参数
* K Map中的键形式参数
* V Map中的值形式参数
* ? 任意匹配的配型参数 <? extends E>/<? super E>
* 有限的通配符形式参数(PECS)
*
* Class<T> 泛型
* Class<String> 参数化的类型
* Class 原生态类型(删除了所有的泛型信息)
* Class<?> 无限制的通配符类型
* Class<? extends E> 有限制的通配符类型
* Class<T extends Comparable<T>> 递归类型限制(用类型参数本身组成表达式限制类型参数)
* <T> 形式类型参数
* <String> 实际类型参数
*
* static <E> E get(E e) 泛型方法
* (<E> 称为类型参数列表,即在调用方法之前告诉编译器,此方法中的类型都是什么类型)
* 编译器使用泛型方法可通过类型推导,推导出类型参数列表的类型
*
* 此内容主要涉及泛型类和泛型方法,测试用例-->testGenericeClass
* 泛型集合-->testGeneCollection
* 有限的通配符使用-->testBoundWildType
* 泛型编译器维护类型信息,运行时舍弃-->testEraseGenericsInfo
* 递归类型参数调用-->testRecursionTypeRestri
* 测试多个类型参数-->testDoubleType
* @author Administrator
*
*/
测试代码
package com.undergrowth.lang;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import org.junit.Test;
/**
* 泛型学习测试代码
*
* 泛型-->类或者接口的声明中拥有一个或多个类型参数时,称为泛型类/泛型接口,简称泛型
* 泛型在安全性和表述性上都比原生态类型更具有优势
* 泛型是不可变的,无法向数组一样形成协变关系
* (Sub extends Super,同时可支持Sub[] extends Super[])
* (Sub extends Super,不支持List<Sub> extends List<Super>)
* 泛型在编译时检查其元素类型信息,而在运行期舍弃其元素类型信息
* 每个类都是自身的子类型和超类型
* T 形式类型参数
* E 集合中的形式类型参数
* K Map中的键形式参数
* V Map中的值形式参数
* ? 任意匹配的配型参数 <? extends E>/<? super E>
* 有限的通配符形式参数(PECS)
*
* Class<T> 泛型
* Class<String> 参数化的类型
* Class 原生态类型(删除了所有的泛型信息)
* Class<?> 无限制的通配符类型
* Class<? extends E> 有限制的通配符类型
* Class<T extends Comparable<T>> 递归类型限制(用类型参数本身组成表达式限制类型参数)
* <T> 形式类型参数
* <String> 实际类型参数
*
* static <E> E get(E e) 泛型方法
* (<E> 称为类型参数列表,即在调用方法之前告诉编译器,此方法中的类型都是什么类型)
* 编译器使用泛型方法可通过类型推导,推导出类型参数列表的类型
*
* 此内容主要涉及泛型类和泛型方法,测试用例-->testGenericeClass
* 泛型集合-->testGeneCollection
* 有限的通配符使用-->testBoundWildType
* 泛型编译器维护类型信息,运行时舍弃-->testEraseGenericsInfo
* 递归类型参数调用-->testRecursionTypeRestri
* 测试多个类型参数-->testDoubleType
* @author Administrator
*
*/
public class GenericsLearn {
/**
* 测试泛型类和方法
*/
@Test
public void testGenericeClass() {
GenericeClass<String> gClass1 = new GenericeClass<String>("测试泛型类参数");
System.out.println(gClass1);
System.out.println(gClass1.getAddSome("泛型方法"));
System.out.println(gClass1.getAddSome(123));
}
/**
* 泛型测试类
*
* @author Administrator
*
* @param <T>
*/
private static class GenericeClass<T> {
private final T t;
public GenericeClass(T t) {
super();
this.t = t;
}
/**
* 获取对象后 添加附加信息
*
* @param t
* @return
*/
public <E> E getAddSome(E t) {
if (t instanceof String) {
// 因为在进入此方法时 已做了类型判断 使用注解消除非受检警告
@SuppressWarnings("unchecked")
E t1 = (E) (String.valueOf(t) + ",附加泛型防范新消息");
return t1;
}
return t;
}
public void iterator(Iterable<? extends T> src) {
for (T t : src) {
System.out.println(t);
}
}
@Override
public String toString() {
return "GenericeClass [t=" + t + "]";
}
}
/**
* 测试泛型集合
*/
@Test
public void testGeneCollection() {
Collection<String> collection = createCollection("123");
/*
* for (Iterator<String> iterator = collection.iterator();
* iterator.hasNext();) { String string = (String) iterator.next();
* System.out.println(string); }
*/
iterator(collection);
}
/**
* 创建测试集合
*
* @return
*/
private <E> Collection<E> createCollection(E t) {
// TODO Auto-generated method stub
Collection<E> collection = Collections.emptyList();
if (t instanceof String) {
collection = new CopyOnWriteArrayList<E>();
// 已经进行类类型检查 所以转换时没有问题的 每个类都是自身的子类型和超类型
@SuppressWarnings("unchecked")
Collection<? extends E> initData = (Collection<? extends E>) Arrays
.asList(new String[] { "测试集合1", "测试集合2", "测试集合3" });
collection.addAll(initData);
}
return collection;
}
/**
* 创建Number集合
* 此方法不推荐使用 这里只是测试使用
* @return
*/
@Deprecated
private <E> Collection<E> createNumber() {
Collection<E> collection = new CopyOnWriteArrayList<E>();
@SuppressWarnings("unchecked")
Collection<? extends E> initData = (Collection<? extends E>) Arrays
.asList(new Number[] { 123.2, Integer.MAX_VALUE, 789 });
// System.out.println(initData.getClass().getName());
collection.addAll(initData);
return collection;
}
/**
* 迭代实现了Iterable接口的可迭代子类
*
* @param src
*/
public <E> void iterator(Iterable<E> src) {
for (E e : src) { // 内部通过迭代器来遍历元素
System.out.println(e);
}
}
/**
* 测试有限的通配符类型 每个类都是自身的子类型和超类型
* PECS原则-->producer-extends,consumer-super
*/
@Test
public void testBoundWildType() {
GenericeClass<Number> gClass1 = new GenericeClass<Number>(123456);
System.out.println(gClass1);
System.out.println(gClass1.getAddSome("123456"));
// 创建Number数组
Collection<Number> collection = createNumber();
iterator(collection);
// 使用GenericeClass的迭代方法进行迭代 每个类都是自身的子类型和超类型
System.out
.println("使用有限的通配符进行迭代 形式为:Iterable<? extends T> 实际为:Iterable<Number extends Number> 每个类都是自身的子类型和超类型");
gClass1.iterator(collection);
Collection<Integer> collection2 = createNumber();
// 使用foreach进行迭代
System.out.println("使用foreach进行迭代");
iterator(collection2);
// 使用有限的通配符进行迭代
System.out
.println("使用有限的通配符进行迭代 形式为:Iterable<? extends T> 实际为:Iterable<Integer extends Number>");
gClass1.iterator(collection2);
System.out.println("进行字符串集合的foreach迭代");
Collection<String> collection3 = createNumber();
iterator(collection3);
System.out.println("如果使用collection3.add(123)方法,泛型的安全性检查就会得到体现,编译器会报错");
// collection3.add(123);
System.out
.println("如果调用gClass1.iterator(collection3)方法,就会有问题,因为形式为:Iterable<? extends T> 实际为:Iterable<String extends Number>");
// gClass1.iterator(collection3);
System.out.println("获取Serializable集合");
Collection<Serializable> collection4 = createNumber();
iterator(collection4);
System.out
.println("之前一直有个疑惑,为什么Collection<Number>、Collection<Integer>、Collection<String>、Collection<Serializable>、Collection<List>调用的时候 能够返回相应的集合,"
+ "因为很明显 在createNumber方法中创建的是Number的List<Number>集合 我们有知道泛型是不可协变的 为什么会成功呢 ");
System.out
.println("因为泛型在编译器检查其类型信息(所以当定义Collection<Serializable> collection4 = createNumber();的时候 调用createNumber,而此方法只会进行类型检查,createNumber为泛型方法,所以编译时是没有问题的),而在运行时丢弃其元素类型信息,并且强制类型转换是在运行期进行的,所以在(Collection<? extends E>)强制类型转换实际上是(Collection)List,所以运行期也没有问题,调试一下就知道了,害我想了1个多小时");
}
/**
* 测试泛型只在编译器维护其类型信息 在运行期不会维护其元素的类型信息
* 下面代码会报错 java.lang.ClassCastException:
* java.lang.Double cannot be cast to java.util.List
*/
@Test
public void testEraseGenericsInfo() {
System.out.println("获取List集合");
Collection<List> collection5 = createNumber();
for (List list : collection5) {
System.out.println(list.get(0));
;
}
}
/**
* 递归类型限制
* 使用类型参数本身组成表达式限制类型参数
*/
@Test
public void testRecursionTypeRestri(){
//Integer和String都实现了Comparable接口
List<Integer> list=Arrays.asList(1,2,3,4);
System.out.println(recurType(list));
List<String> listString=Arrays.asList("1","2","3","4");
System.out.println(recurType(listString));
//自定义实现的Comparable接口
List<CustomComparable> listCustomComparables=Arrays.asList(new CustomComparable(10),new CustomComparable(20),new CustomComparable(30));
System.out.println(recurType(listCustomComparables));
}
/**
* 找到列表中的最大值
* @param list
* @return
*/
private <T extends Comparable<T>> T recurType(List<T> list){
T to=list.get(0);
for (Iterator<T> iterator = list.iterator(); iterator.hasNext();) {
T t = (T) iterator.next();
if(to.compareTo(t)<=0) to=t;
}
return to;
}
/**
* 多个类型参数调用
* 多个类型参数
* 其中一个参数要么与泛型类相关联 iterator(Iterable<? extends T> src)
* 要么与静态方法关联 GenericsLearn.<Number>doubleType
*/
@Test
public void testDoubleType(){
Collection<Integer> collection=Arrays.asList(1,2,3);
Collection<Number> collection2=GenericsLearn.<Number>doubleType(collection);
System.out.println("使用泛型方法传递多个类型参数");
for (Number number : collection2) {
System.out.println(number);
}
}
public static <E> Set<E> doubleType(Collection<? extends E> collection){
Set<E> set=new HashSet<>();
for (Iterator<? extends E> iterator = collection.iterator(); iterator.hasNext();) {
E e = (E) iterator.next();
System.out.println(e);
set.add(e);
}
return set;
}
@Test
public void testOther() {
Integer integer = (int) 13.2;
String aString = String.valueOf(13.2);
}
/**
* 自定义比较器
* @author Administrator
*
*/
class CustomComparable implements Comparable<CustomComparable>{
private final int num;
public CustomComparable(int num){
this.num=num;
}
@Override
public int compareTo(CustomComparable o) {
// TODO Auto-generated method stub
if(this.num>o.num) return 1;
else if(this.num==o.num) return 0;
else return -1;
}
@Override
public String toString() {
return "CustomComparable [num=" + num + "]";
}
}
}
附加一个 泛型中最复杂的用法 时间:2015-6-13
类型限界--在尖括号中指出,它指定的参数类型必须具有某种性质
例如:
public static <anytype> anytype findMax(anytype[] arr){
int maxIndex=0;
for(int i=1;i<arr.length;i++){
if(arr[i].compareTo(arr[maxIndex])>0) maxIndex=i;
}
return arr[maxIndex];
}
更好的做法
public static <anytype extends Comparable<anytype>> ...
但是 此种方法会因为泛型的不可协变 导致子类无法使用
举个例子,假如Shape实现Comparable<Shape>,Square继承Shape,那么Square也是实现了Comparable<Shape>,Square is-a Comparabe<Shape>,
但是因为泛型不可协变,导致于 Square is-not-a Comparable<Square>,为了解决此问题
更好的做法
public static <anytype extends Comparable<? super anytype>> ...