前言
使用Java的时候,我们都在用泛型,可是泛型究竟是什么,泛型的机制是什么?泛型为什么在运行时不能获取他的类型?泛型中的限定符到底代表什么意义?感觉应该好好了解下泛型的使用。
为什么使用泛型?
通常我们设计一个方法的时候,为了让方法更加通用,我们经常使用的就是多态(父类 接口等)。例如:
public static void sort(ArrayList list){};
public static void sort(List list){};
public static void sort(Collection collection){};
更明显的就是最后一个方法更加的通用,可以接受任何Collection的子类。
如果想要比接口更大的通用性怎么办?Object or 泛型
泛型的实现原理
Java泛型的核心概念:告诉编译器想使用什么类型,编译器帮助你处理一切的细节。
泛型擦除
由于Java为了能够实现向上兼容性,就不得不保证,在实际运行的时候(机器码)根本不存在泛型这种东西。换言之Java泛型只是个语法糖。并没有修改Java的底层机制。只能在编辑器上做一些处理。
泛型的擦除是擦出到边界
? super List 擦除的边界为List
T 擦除的边界为Object
引用编程思想的话:
泛型中的所有动作都发生在边界处,对传递过来的进行额外的编译检查,并插入对传递出去值的转型
其实这点不是很明白,如果在javac的时候,就体现不出来不同,那么运行的时候,怎么可能转型???不是很明白
Class c1 = new ArrayList<Integer>().getClass();
Class c2 = new ArrayList<String>().getClass();
//两个不同泛型的类是一个类
System.out.println(c1 == c2);//true
//得到对应的泛型类型竟然是个占位符!!!
//泛型代码内部,无法获取任何有关的泛型参数类型的信息
Arrays.toString(c1.getTypeParameters())//[E]
擦除的补偿
1.擦除导致了不知道泛型的类型信息,因此只能传递一个类型标签解决(多传递一个Class对象)
2.泛型数组:一班的解决方案是在任何想要创建泛型数组的地方都适 用ArrayList(因为有了擦除,数组的运行时类型只能是Object[])
泛型类和泛型方法的区别
泛型方法使改方法能够独立于类而产生变化,并且可以使用类型推断
public class New {
public static <T> List<T> list(){
return new ArrayList<T>();
}
public static void main(String[] args) {
//隐式使用类型
List<String> list = list();
//显示使用类型
New.<String>list ();
}
}
边界
List<’?’ extends Fruit>:具有任何从Fruit继承的类型的列表,但是不知道这个具体的类型是什么。
? extends Fruit 代表了一种具体的类型,但是木有指定具体类型,只能进行向上转型
public class New {
public static void main(String[] args) {
List<? extends Fruit> list = new ArrayList<>();
//Complier Error:cannot add any type of object
list.add(new Apple());
//Complier Error:cannot add any type of object
list.add(new Fruit());
list.get(1).eat();
}
}
class Fruit{
void eat(){};
};
class Apple extends Fruit{};
class Banana extends Fruit{};
? super Myclass :代表的是某一个Myclass的超类
public class New {
public static void main(String[] args) {
List<? super Apple> list = new ArrayList<>();
list.add(new Apple());
//Complier Error:cannot add any type of object
list.add(new Fruit());
}
}
class Fruit{
void eat(){};
};
class Apple extends Fruit{};
class Banana extends Fruit{};
List
public class Holder<T> {
Object o;
T get() {
return (T) o;
}
void set(T t) {
o = t;
}
public static void main(String[] args) {
Holder holder = new Holder();
holder.set(new String("11"));
holder.set(3);
Holder<?> holder2 = new Holder();
//can not complier
holder2.set(3);
Object o = holder2.get();
}
}
最后给大家在上一个编程思想的例子:
public static <T, S extends Iterable<? extends T>>
void apply(S seq, Method method,Object... args) {
try {
for (T t : seq) {
method.invoke(t, args);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Java编辑器优化:
http://blog.csdn.net/u010169705/article/details/51288788