泛型
泛型又名参数化类型,是JDK5出现的新特性
★★★为什么需要泛型★★★
①可以对加入到集合的数据类型进行约束,以防加入的数据类型不合理
②遍历集合需要进行类型转换,当集合非常多元素时,这就会效率很慢,而如果使用泛型,由于泛型要求集合装的都是同样类型的元素,在进行增强for循环时,就直接把辅助对象定义为对应类型,而不需要是Object类,也就是说不用进行类型转换,提高了效率。
③用泛型可以保证,如果在编译时没有发出警告,那么运行时不会出现ClassCastExpection异常,而且代码也能更简洁,更健壮
★★★泛型语法★★★
泛型语法上作用是:可以在类声明的时候用一个标识符来表示一种数据类型,到底是哪种数据类型要在创建对象的时候才能确认,上一个例子看看
public class Test { public static void main(String[] args) { new A("卡梅隆安东尼"); //可以指定 new A("卡梅隆安东尼"); //也可以不指定,编译器会根据你赋予的值的类型来确定T,这里就会是String new A (1); //报错,因为指定只能放String new A(); //无参构造器,泛型默认是Object } } class A { //T在创建对象的时候确定, // 即在编译期间会确定这个T代表什么数据类型 T a; public A(T a) { this.a = a; System.out.println(a.getClass()); } public T a(T a){ return a; } public A(){}; }
①<>里面只能放引用类型,不能放基本数据类型,不过也只是确定的时候不能指定基本数据类型,如果是作为形参传递,会自动装箱成包装类
第一条虽然传的整形参数会被自动装箱成包装类Integer
②一些特殊的写法
<?>:支持任意泛型类型
<? extends A>:支持A类以及A的子类,规定了泛型的上限
<? super A>:支持A类及A的父类,不限于直接父类,规定了泛型的下限
自定义泛型
语法:
class /interface 类名/接口名
成员
}
①这种含有自定义泛型的类或者接口,叫做自定义泛型类或者自定义泛型接口,类和接口(接口没有普通属性)的普通成员可以使用泛型(属性,方法),静态方法和静态属性中不能使用类的泛型,因为如果是用了类名来访问静态成员,你没办法去指定泛型是哪种类型
②使用泛型的数组,不能初始化,因为T还没确定
③泛型类的类型,是在创建对象的时候确定的,如果创建对象时没有指定类型,默认Object
自定义泛型接口的泛型,在继承接口或者实现接口的时候确定,如果没有指定,默认Object
④指定了类型后的泛型类,不具有继承性(不是指泛型属性和泛型参数),除非用上面的特殊写法
public class Test { public static void main(String[] args) { Object o = new String(); //这里可以把A//并且这两个新类型<>里面没写继承关系,因此是不具备继承关系的,所以向上转型失败 A
不具备继承性只是诸如类型<指定的类型>这种存在的,因为这样相当于新类型,若想有继承关系必须要在<>里面说明,但是泛型属性和泛型参数只是通过泛型来确定自身的类型,没有形成新类型,所以该干嘛还是干嘛
自定义方法
语法:
修饰符
}
①泛型方法可以定义在普通类中,也可以定义在泛型类中
②当泛型方法被调用时,类型才会被确定
public class Test { public static void main(String[] args) { A a = new A("1"); a.a(1); } } class A{ public T c; public A(T c) { this.c = c; } public void a(T b){ System.out.println(b.getClass()); } }
运行结果
class java.lang.Integer
可见,即便前边有确定了c的泛型T,也不关a方法的T的事,它们是独立开的
③泛型紧跟其后的才是泛型方法,在参数列表的泛型只是说明方法使用了泛型
class A { //自定义泛型方法,这个泛型专属于这个方法 publicvoid a(T b){ System.out.println(b.getClass()); } //方法使用了泛型 public void b(T b){ System.out.println(b.getClass()); } }