泛型代码和虚拟机
虚拟机没有泛型类型对象——所有对象都属于普通类。在泛型实现的早期版本中,甚至能够将使用泛型的程序编译为在1.0虚拟机上运行的类文件!这个向后兼容性在Java泛型开发的后期被放弃了。如果使用Sun的编译器来编译使用Java泛型的代码,结果类文件将不能在5.0之前的虚拟机上运行。
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型(raw type)。原始类型的名字就是删去类型参数后的泛型类型名。擦除(erased)类型变量,并替换为限定类型(无限定的变量用Object)。
例如,Pair<T>的原始类型如下所示:
public class Pair
{
public Pair(object first, object second)
{
this.first=first;
this . second = second ;
}
public object getFirst(){
return first;
}
public object getSecond() {
return second;
}
public void setFirst(0bject newValue){
first=newValue;
}
public void setSecond(obiect newvalue) {
second newvalue;
}
private object first;
private Object second;
}
因为T是一个无限定的变量,所以直接用Object替换。结果是一个普通的类,就好像泛型引入Java语言之前已经实现的那样。在程序中可以包含不同类型的Pair,例如,Pair<String>或Pair<GregorianCalendar,而擦除类型后就变成原始的Pair类型了。
C++注释:就这点而言,Java泛型与C++模板有很大的区别。C++中每个模板的实例化产生不同的类型,这一现象称为“模板代码膨胀”。Java不存在这个问题的困扰
有泛型和无泛型的差异
import java.util.*;
public class 泛型 {
public static void main(String[] args) {
/**
* 无泛型
*/
List s1 = new ArrayList();
s1.add(20);
Integer s = (Integer) s1.get(0);
//当我们把数据传进去的时候,
//都是以Object的类型进行储存的。
//取出来也是Object类型的。
//因为父类是不能访问到访问子类的数据的,
//如果要变成子类,就得要强制转换。
System.out.println();
/**
* 有泛型
*/
List<Integer> s2 = new ArrayList<>();
s2.add(22);
//相比于上面没有泛型的程序
//这里少了类型转换这一步,
//因为我们的泛型已经指定了,
//我们往集合里添加的元素就是整数。
//我们通过get方法取出来的元素也是整数。
//C++里泛型也叫模板
Integer b = s2.get(0);
Set<String> ss = new HashSet<>();
ss.add("Hello");
ss.add("World");
ss.add("!");
//所有集合都有一个Iterator方法,
//它也可以用泛型。
//但是,迭代的时候,其尖括号里面的属性,
//也应该是与上面集合对应的属性。
//比如上面Set的属性是String类型,
//迭代的就应该是String类型。
Iterator<String> iter = ss.iterator();
while (iter.hasNext()) {
//这里用next返回
String str = iter.next();
System.out.println(str);
}
}
}
Map函数的泛型
import java.util.*;
public class 泛型 {
public static void main(String[] args) {
/**
* Map函数的泛型
*/
Map<String, Student> stus = new HashMap<>();
stus.put("zhangsan", new Student(123, "zhangsan", 'm'));
stus.put("lilsi", new Student(124, "lisi", 'm'));
stus.put("wangmazi", new Student(125, "wangmazi", 'm'));
//Entry是Map里面的静态集合
//而我们在这里将Set<Map.Entry<String, Student>>类型全部规定好,
//就省去了类型转换的麻烦。
Set<Map.Entry<String, Student>> entrySet = stus.entrySet();
Iterator<Map.Entry<String, Student>> ite1 = entrySet.iterator();
while (iter.hasNext()) {
Map.Entry<String, Student> entry = ite1.next();
System.out.println(
entry.getKey() + ":" +
entry.getValue().getName() + ":" +
entry.getValue().getId() + ":" +
entry.getValue().getSex());
}
}
}