泛型的作用:
1,避免了在操作集合时强制转换的麻烦。
2,将运行时期的ClassCastException转到了编译时期。
泛型是JDK1.5才出现的新特性,在此之前,在想集合中存储数据时都会向上提升为Object,再取出时候使用时会十分麻烦
@Testpublic voidtest1(){
ArrayList arr= newArrayList();
arr.add(newPerson());//添加时会向上提升为Object,所以取出来时需要进行强转
Person p = (Person) arr.get(0);
}
由于经常需要进行我们手动进行强制转换类型,这样不可避免就会引发程序的一些安全问题
@Testpublic voidtest1(){
ArrayList arr= newArrayList();
arr.add("111");//这样运行强转会发现错误,但是编译时发现不了
Integer in = (Integer)arr.get(0);
}
JDK5中的泛型运行程序员在编写代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性。
泛型的基本使用:
1,在集合上
合法的定义:
ArrayList arr = new ArrayList();
ArrayList list = new ArrayList();
ArrayList list1 = new ArrayList();
后面两种语法主要是为了向下兼容
例如:以前的方法:public void aa(ArrayList list)
为了使aa(new ArrayList)能够使用才存在的
2,在方法上的定义
@Test
public void aa(T t){
}
3,在类上定义。如果类里有很多方法都使用了同一泛型,每次都要声明太过麻烦,可以在类里声明泛型,这个泛型就作用于整个类
public class Genericity {
@Test
public void test3(K k){
}
}
注意:在类声明的泛型对静态成员无效,静态成员必须在static后面自己声明泛型
public static void test4(K k){
}
此外,如果两个方法只是泛型不一样,这样并不属于方法的重载
@Test
public void test1(){
test2();
}
//只是泛型不同并不属于方法的重载
public void test2(T t){
}
public void test2(Q q){
}
4,在接口上:
如果接口上声音了一个泛型T,那么在实现的时候就对这个T进行明确,明确不了的话,可以将T泛型进行
重新定义,改成Q或者K
interface Inter{public voidshow(T t);
}//实现了带泛型的接口,实现类要明确泛型类型
class ImpClass implements Inter{
@Overridepublic voidshow(String t) {//TODO Auto-generated method stub
}
}//如果还是明确不了,那么就必须重新定义泛型。不能使用原来的T,如果不定义泛型,那么就变自动将接口的泛型变为Objcet
class ImpClass2 implements Inter
{
@Overridepublic voidshow(Q t) {//TODO Auto-generated method stub
}
}
泛型的限定:
? extends E: 接受E类型或者的子类型对象------上限
? super E: 接受E类型或者E的父类型----------下限
那么什么时候使用上限?什么时候使用下限呢?
一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患
什么时候用下限呢?通常对集合中的元素进行取出操作时,可以是下限
泛型的通配符:?
?表示未知类型
T也是表示未知类型,那么T和?的区别在哪?
?和T的区别,在使用时,T可以明确到具体的类型,可以进行具体的操作,即T类型可以进行操作,?不行
泛型的擦除:
泛型技术室给编译器使用的技术,用于编译时期,确保了类型的安全,运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。这个是为了兼容运行时的类加载器