Java泛型到底什么,在看《数据结构与算法分析》一书时我不禁问自己。其书中介绍甚为抽象,本人就想试着用程序实验一下java泛型。参考了小顾问@cnblogs的关于java泛型的博文。本人的理解Java泛型其实就是参数类型的类型。
泛型基础
/**
*
* @author wqh
* 泛型基础
*/
public class GenericDemo1 {
/**
* 未使用泛型
*/
public static void test0() {
Map m = new HashMap();
m.put("key", "yes");
String s = (String) m.get("key");// 类型强制转换
}
/**
* 未使用泛型
* 没进行型强制转换,无法通过编译
*/
public static void test1() {
Map m = new HashMap();
m.put("key", "yes");
//String s = m.get("key");// 无类型强制转换,编译无法通过
}
/**
* 未使用泛型
* map中保存了Integer类型的对象,运行时抛出 ClassCastException
*/
public static void test2() {
Map m = new HashMap();
m.put("key", new Integer(3));// 值可为任意对象,编译可以通过
String s = (String) m.get("key");// 类型强制转换
}
/**
* 使用泛型
* 注意Map的声明,声明时就指定了变量的类型,
* Map<String, String>类型的对象,Map.put()方法参数类型必须为String,
* Map.get()方法 将会得到 String 类型.
* map中保存了Integer类型的对象,编译无法通过
*/
public static void test3() {
Map<String, String> m = new HashMap<String, String>();// 使用泛型
// m.put("key", new Integer(3));//编译无法通过
String s = m.get("key");// 不需要类型强制转换
}
/**
* 使用泛型
*
*/
public static void test4() {
Map<String, String> m = new HashMap<String, String>();// 使用泛型
m.put("key", "yes");// 编译通过
String s = m.get("key");// 不需要类型强制转换
}
public static void main(String[] args) {
test2();//抛出 ClassCastException
}
/**
* 以上代码可以看出,如果使用泛型
* 1.保存在Map中值的类型错误时不能编译通过,类型安全
* 2.在获取值时不需要进行强制类型转换,提高可靠性并加快开发速度
* 结论:泛型消除代码中的强制类型转换,并且进行类型检查!!!
*/
}
泛型通配符
/**
*
* @author wqh
* 泛型通配符
*/
public class GenericDemo2 {
/**
* 数组是协变的,意思是在可以需要用numberArray的地方使用intArray
*/
private void test0() {
Integer[] intArray = new Integer[10];
Number[] numberArray = intArray;
}
/**
* 泛型不是协变的,不可以在需要listObject的地方使用listString
* String是Object的子类,但是List<String>和List<Object>却没有这种继承关系
*/
public static void test1(){
List<Object> listObject = new ArrayList<Object>();
List<String> listString = new ArrayList<String>();
}
/**
* 如果泛型协变的,就会违背泛型应该提供的类型安全
* Integer和Float不是同一种类型
*/
public void test2() {
List<Integer> intList = new ArrayList<Integer>();
List<Number> numberList = intList; // 编译不通过,无效代码
numberList.add(new Float(3.1415));//违背泛型应该提供的类型安全
}
/**
* printList1方法的参数类型只能是List<Object>,调用时传入List<Integer>编译不能通过
*
*/
public void printList1(List<Object> l) {
for (Object o : l){
System.out.println(o);
}
}
/**
* 为了灵活使用泛型,引入类型通配符。
* printList2方法的参数类型可以是
* List<Object>、List<Integer> 或 List<List<List<Object>>>
*
*/
public void printList2(List<?> l) {
for (Object o : l) {
System.out.println(o);
}
}
/**
* 类型通配符?的作用
* 编译器不知道 List的类型参数的值,但是编译器可以推理,
* 它推断未知的类型参数必须扩展 Object
* 1.但是编译器不能对 List的类型参数作出足够严密的推理,
* 以确定将 Integer 传递给 List.add() 是类型安全的
* 所以lu.add的方法编译不通过
* 2.不依赖于编译器必须知道关于lu的类型参数的方法
* 则是可以编译通过的,例如lu.clear()
*/
public void test4() {
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
List<?> lu = li;
System.out.println(lu.get(0));
lu.add(new Integer(4)); // 编译无法通过
lu.clear();
}
}
泛型方法
/**
*
* @author wqh
* 泛型方法
*
*/
public class GenericDemo3 {
/**
* 泛型方法是为了想要在该方法的多个参数之间宣称一个类型约束
* ifThenElse方法不用显式地告诉编译器T是什么值,
* 编译器可以使用类型推理来推断出
*/
public <T> T ifThenElse(boolean b, T first, T second) {
return b ? first : second;
}
/**
* 调用方法ifThenElse
*/
private void test0() {
String s1 =
ifThenElse(true, "a", "b");
//编译通过:"a","b"是String类型,类型相同
Integer i =
ifThenElse(false, new Integer(1), new Integer(2));
//编译通过:new Integer(1), new Integer(2)
//是Integer类型
String s2 =
ifThenElse(false, "pi", new Float(3.14));
//编译不通过:"pi", new Float(3.14)类型不同
}
/**
* 在还没有完全指定类型参数时,需要对类型参数指定附加的约束
* 类型参数 V 被判断为由 Number限制 。
* 在没有类型限制时,假设类型参数由 Object限制
*/
public class Matrix<V extends Number> { }
/**
* 允许创建Matrix<Number>、Matrix<Integer>类型的对象,
* 但是不允许创建Matrix<String>的对象
*/
private void test1() {
new Matrix<Number>();//编译通过
new Matrix<Integer>();//编译通过
new Matrix<String>();//编译不通过
}
}
泛型高级
/**
*
* @author wqh
* 泛型高级
* 此部分内容本人理解也不是很好,不是很详尽,Selector的东西还需要研究
*/
public class GenericDemo4 {
/**
* Java类库中的泛型
* 该定义组合了通配符类型参数和有限制类型参数,
* 允许您将 Collection<Integer> 的内容添加到 Collection<Number>。
*/
interface Collection<V> {
boolean addAll(Collection<? extends V> paramCollection);
}
/**
* 二元 max() 方法的实现
* 使用泛型方法和有限制类型参数
*/
public static <T extends Comparable<T>> T max(T t1, T t2) {
if (t1.compareTo(t2) > 0)
return t1;
else
return t2;
}
/**
* 让 T.class是 Class<T> 类型的好处是,通过类型推理,
* 可以提高使用反射的代码的类型安全
* 还不需要将 T.class.newInstance()强制类型转换为T
* 此方法实现从数据库检索一组对象,并返回 JavaBeans 对象的一个集合
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static <T> List<T> getRecords(Class<T> c, Selector s) throws
InstantiationException, IllegalAccessException {
// Use Selector to select rows
List<T> list = new ArrayList<T>();
for (/* iterate over results */;;) {
T row = c.newInstance();
// use reflection to set fields from result
list.add(row);
}
}
/**
* 用 Class<T> 替换 T[]
* Collection 接口还没有改变为使用该技术,
* 因为这会破坏许多现有的集合实现
* 但是如果使用泛型从新构建 Collection,
* 则当然会使用该方言来指定它想要返回值是哪种类型。
* 调用:Integer[] integer = new GenericDemo4().toArray(Integer.class);
*
*/
public <T> T[] toArray(Class<T> returnType) {
//未实现
return null;
}
}
一个简单的泛型类
/**
*
* @author 小顾问@cnblogs
*
* @param <V>
* 一个简单的泛型类,类似于 List,充当一个容器
* 泛型类最常见的用例是容器类(比如集合框架)
* 或者值持有者类(比如 WeakReference 或 ThreadLocal)
*/
public class SimpleGenericList<V> {
private V[] array;
private int size;
public SimpleGenericList(int capacity) {
array = (V[]) new Object[capacity];
//List构造函数的一种可能的实现
}
public void add(V value) {
if (size == array.length)
throw new IndexOutOfBoundsException(Integer.toString(size));
else if (value == null)
throw new NullPointerException();
array[size++] = value;
}
public void remove(V value) {
int removalCount = 0;
for (int i = 0; i < size; i++) {
if (array[i].equals(value))
++removalCount;
else if (removalCount > 0) {
array[i - removalCount] = array[i];
array[i] = null;
}
}
size -= removalCount;
}
public int size() {
return size;
}
public V get(int i) {
if (i >= size)
throw new IndexOutOfBoundsException(Integer.toString(i));
return array[i];
}
}
/**
*
* @author 小顾问@cnblogs
* 作为从原始集合类型迁移到泛型集合类型的帮助,
* 集合框架添加了一些新的集合包装器,
* 以便为一些类型安全 bug 提供早期警告
*/
public class Collections {
public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type ) {
return new CheckedCollection<E>(c, type);
}
//省略了部分Collection<E>中定义的接口的实现
private static class CheckedCollection<E> implements Collection<E> {
private final Collection<E> c;
private final Class<E> type;
CheckedCollection(Collection<E> c, Class<E> type) {
this.c = c;
this.type = type;
}
public boolean add(E o) {
if (!type.isInstance(o))
throw new ClassCastException();
else
return c.add(o);
}
}
}