---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
Java中的范型使用起来特别轻松:
List<String> list = new ArrayList<String>();
list.add("abc"); // ok !
//list.add(123); error!
这仅仅是泛型的最简单的应用,我们知道,java的泛型是编译时会擦除的:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(100);
list.add(200);
list.add(300);
Class<?> clazz = list.getClass();
Method method = clazz.getMethod("add", Object.class);
method.invoke(list, "哈哈");
for(int i=0; i<list.size(); i++){
System.out.print(list.get(i) + " ");
}
通过反射在运行时给list添加元素,此时泛型已经擦除,所以可以添加String类型的元素了。
这下打印出来的结果是 : 100 200 300 哈哈
说到底,泛型可以让我们在实际编程时不容易出错,但是要真正用好泛型也不是很容易的事:
定义一个接口:
public interface Stack<T> {
public T pop();
public void push(T t);
public void pushAll(Iterable<T> it);
public void popAll(Collection<T> coll);
}
实现类:
public class MyStack<T> implements Stack<T>{
public T pop() {
return this.list.remove(0);
}
public void push(T t) {
this.list.add(0, t);
}
public void pushAll(Iterable<T> it) {
for(T t : it){
this.push(t);
}
}
public void popAll(Collection<T> coll) {
while(list.size() != 0){
coll.add(this.pop());
}
}
private List<T> list = new ArrayList<T>();
}
接下来使用该类:
Stack<Number> stack = new MyStack<Number>();
stack.push(1);
看起来ok,继续:
List<Integer> integers = new ArrayList<Integer>();
stack.pushAll(integers);
此时编译器就通不过了,报出了 : Stack<Number> connot be applied to (Interable<Integer>) 错误
我的想法是: pushAll的参数不应该是T的Iterable接口,应该是T的某个子类型的Iterable接口,正好,java中有一个通配符正合此意,于是将代码改成下面这样:
/*
* 此处如果是Iterable<T>编译时会报错,此处我们的希望是T的某种子类型的Iterable接口而不是T的Iterable接口
*/
public void pushAll(Iterable<? extends T> it) {
for(T t : it){
this.push(t);
}
}
ok,正常了,继续:
Collection<Object> coll = new ArrayList<Object>();
stack.popAll(coll);
此时又不通过了,报出了: Collection<Object> 不是 Collection<Number>的子类型,这和刚才的错误差不多,我的意思不是T的集合,而是T的某种超类的集合,java也正好有个通配符正符合此意,于是将代码改成这样:
/*
*Collection<T> 编译时会出错,我们此处的愿望是T的某种超类的集合而不是T的集合
*/
public void popAll(Collection<? super T> coll) {
while(list.size() != 0){
coll.add(this.pop());
}
}
ok,正常了,在整体性的试一试:
Stack<Number> stack = new MyStack<Number>();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
List<Integer> integers = new ArrayList<Integer>();
stack.pushAll(integers);
Collection<Object> coll = new ArrayList<Object>();
System.out.println(stack.pop());
stack.popAll(coll);
for(Object obj : coll){
System.out.println(obj);
}
嗯,一切OK!!!
java中泛型我觉得有一种很好的用法 : 类型安全的异构容器:
public interface Favorite {
public <T> void putFavorite(Class<T> type,T instance);
public <E> E getFavorite(Class<E> type);
}
实现类非常非常简单:
public class MyFavorite implements Favorite{
public <T> void putFavorite(Class<T> type,T instance){
if(type == null){
throw new NullPointerException("type为空!");
}
map.put(type, instance);
}
/*
* getFavorite方法 使用了Class的cast方法,将对象动态的转换成了Class对象所表示的类型
* 该方法只检验它的参数是否为Class对象所表示的类的是咧,如果是则返回参数,否则就抛出ClassCastException异常
*/
public <E> E getFavorite(Class<E> type){
return type.cast(map.get(type));
}
Map<Class<?>,Object> map = new HashMap<Class<?>,Object>();
}
我来试试好不好用:
Favorite favorite = new MyFavorite();
favorite.putFavorite(String.class, "哈哈");
favorite.putFavorite(Integer.class, 100);
System.out.print(favorite.getFavorite(String.class) + " ");
System.out.print(favorite.getFavorite(Integer.class));
输出结果: 哈哈 100