18-1,泛型-概述
1,泛型是JDK1.5出现的新技术,新技术的出现是为了解决问题。
2,泛型可以用于明确一个集合中存储什么类型的元素
ArrayListal = new ArrayList (); al.add("abc");//正确 //al.add(3);//编译直接报错 //在迭代器上加上泛型,下面取出来的时候就不用强转了 Iterator it = al.iterator(); while(it.hasNext()) { //在这里不用强转了,因为从it中取出的肯定是String String str = it.next(); System.out.println(str); }
3,好处
(1)将运行时间的问题ClassCastException转到了编译时期。
(2)避免了强制转换的麻烦。
4,泛型什么时候用呢?
当操作的引用数据类型不确定的时候,就用泛型,将要操作的引用数据类型写在<>中即可。其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类型或者接口,就要明确传入的具体引用数据类型。
也可以同时接受多个数据类型:
class ToolTool t = new Tool ();
18-2,泛型-擦除&补偿
1,泛型解决了编译时期的安全问题,是给编译器使用的技术。
2,运行时,会将泛型去掉,生成的class文件中是不带有泛型的,这个称为泛型的擦除。
为什么要擦除呢?
因为为了兼容运行时的类加载器,因为泛型是JDK1.5的新特性,如果class文件中加上泛型的话,类加载器会不认识,若想要类加载器认识泛型,类加载器也要升级,为了避免升级类加载器的麻烦,泛型将交由编译器处理,编译通过后就会把他删去,使之前的类加载器也能运行它。
3,泛型的补偿:
擦除后,如果对元素进行取出的赋值动作,如:String str =it.next();是否需要加上强转呢?答案是不用了,首先,加上泛型且编译通过就能保证集合中的数据是指定的类型了,所以认为不会出现规定类型以外的元素。其实,在运行时,是自动添加了一步动作,通过用getClass()方法获取元素的类型再对其进行一次转换动作,就不用使用者在强制转换了。
18-3,泛型-在集合中的应用
1,以TreeSet为例,TreeSet具备比较功能,但存入的类型必须实现Comparable接口并实现了里面的compareTo方法才可以;或者定义一个比较器,实现Comparator接口并实现里面的compare方法也可以。定义TreeSet时,如果不加泛型Eclipse等IDE会有黄色波浪线提示,加上泛型,黄色波浪线即可消失。
2,上一章提到的Person类实现Comparable接口时Comparable接口也需要指定泛型,如:Comparable
class Person implements Comparable{ ...code... public int compareTo(Person p) { //Person p = (Person)p;//强转可以省去,因为定义了泛型 int temp = this.age = p.age; return temp == 0 this.name.compareTo(p.name) : temp; } ...code... }
18-4,泛型类
1,以前定义工具类的时候这么定义:
public class Tool {
private Object object;
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
别的类用这个工具类的时候,可以这样做:
Tool tool = new Tool(); /* 这里因为没有Worker这个类,所以是错误的。 Worker为传入的错误值,但编译不会报错,因为Tool中接收的是Object类型, 下面的语句必须做强转才能匹配类型,因为把Worker向上提升为了Object。 */ tool.setObject(new Worker()); Student stu = (Student)tool.getObject();
工具类是针对所有类型的,而任何一个类都是Object的子类,所以根据多态的特性,通过将参数定义成Object我们就可以使这个方法接收所有类型的参数,在没有泛型的时候我们就只能这么做。
在JDK1.5之后,使用泛型来接收类中要操作的引用数据类型,这就是泛型类。
泛型类什么时候用呢?
当类中的操作的引用数据类型不确定的时候,就是用泛型来表示。
例如:
public class Tool{ private Q q; public Q getObect() { return q; } public void setObject(Q object) { this.q = object; } }
有泛型后,在别的类用到工具类的时候,可以这么做:
Tooltool = new Tool (); //tool.setObject(new Worker());//编译报错,因为有了泛型指定的Student,所以别的不能进入集合。 tool.setObject(new Student()); Student stu = tool.getObject();
18-5,泛型方法
1,在18-4中有泛型的Tool类中加入泛型方法,Tool
public class Tool{ private Q q; public Q getObect() { return q; } public void setObject(Q object) { this.q = object; } /* 如果方法不加泛型会报错,因为Tool明确只能接收QQ类型, 所以不能操作W类型,要想让其中一个方法操作W类型, 必须在返回值类型前加上泛型。 */ public void show(W str) { System.out.println("show" + str.toString()); } /* 另外,print接收的是字符串,那么能不能打印字符串的长度呢? 答案是不能的,因为QQ str = "abc"(这里假设传入abc),将"abc"提升为QQ类型, QQ类型不知道String类型中的特有方法length(),所以不能打印。但由于QQ也 继承自Object,所以可以使用Object中的方法。 */ public void print(QQ str) { System.out.println("print" + str); } }
调用的时候:
Tooltool = new Tool (); tool.show(new Integer(4));//因为show加了泛型,所以可以接受Tool定义的String以外的类型。 tool.show("abc");//符合To