——每天的寥寥几笔,坚持下去,将会是一份沉甸甸的积累。
1.泛型出现的原因:可以使编写的代码得到重用。
不过,要实现代码重用,用Object的继承也可以实现,不过用Object会出现各种类型转换的麻烦,因此出现了泛型程序设计。
2.泛型的使用
(1)泛型类
在类名后加一对<>,<>里面可以放多个形式类型参数,如E,K,V
public class Pair<T> {
private T first;
public T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}
(2)泛型方法
在方法返回类型和修饰符中间,用<>括起形式类型参数,然后方法的返回类型和参数中都可用到该形式参数
泛型方法可以定义在泛型类中,也可以定义在一般类中
public static <T> T[] getElement(T[] obj){
return obj;
}
3.术语介绍
参数化类型 List<String>
形式类型参数 E
实际类型参数 String
泛型 List<E>
原生态(原始)类型Raw Type List
有限制类型参数 <E extends Number>
无限制通配符类型 <?>
递归类型参数 <T extends Comparable<T>>
有限制通配符类型 <? extends Number>
泛型方法 static <E> List<E> asList(E[] a)
类型令牌 String.class
4.泛型限定的注意点——有限制类型参数
(1)<T extends BoundingType>:T和BoundingType可以都是类,则T是子类;两者也可以都是接口,则T是子接口
(2)一个类型变量或通配符可以有多个限定,如<T extends BoundingType1&BoundingType2>,中间用&连接,而且只能有一个类,可以有多个接口,如果有类存在,必须写在第一个。
5.通配符的使用
1、无限定通配符 形式<?>
2、上边界限定通配符 形式< ? extends Number>
3、下边界限定通配符 形式< ? super Number>
举个例子:
public class Pair<T> {
private T first;
public T second;
public Pair(){
this(null, null);
}
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
public static void main(String[] args) {
//上边界通配符类型
<span style="font-size:12px;"> Pair<? extends Number> pair = new Pair<>();
//pair.setFirst(11);
//出错,因为上边界限定符中,?表示Number的某一子类,在没有确定是哪个子类的前提下,setFirst都将报错
pair.setFirst(null);
//不报错。因为null是任意类的子类。这里只有填null,其他任何Number的子类都将编译不通过
Number num = pair.getFirst();
//将赋值的引用类型写成Number,那么get方法将不会有任何问题,因为返回类型都是Number的子类,赋给父类没问题
//----------------------------------//
//下边界通配符类型
Pair<? super Number> pair01 = new Pair<>();
pair01.setFirst(11);
//换成下边界时,set方法将变得安全,因为?是Number的父类,所有set方法中的参数只要是Number的子类型都将符合为?的子类型
Object i = pair.getFirst();
//使用get方法时,就不能确定得到的到底是什么类型,唯有用Object类型引用,但这样是不安全的。</span>
//----------------------------------//
//无限定通配符类型
Pair<?> pair02 = new Pair<>();
pair02.setFirst(null);//唯有set Null
Object o = pair02.getFirst();//唯有返回Object,但不能set,有如何get,得到的o只能也是null
}
}
所以,有如下原则:
当使用get方法时,尽量用上边界限定通配符
当使用set或add方法时,尽量使用下边界限定通配符
6.泛型的子类型,继承问题
(1)若B extends A,但是List<A>和List<B>没有继承关系。不然List<B>强转成List<A>后可以随便添加和B无关的其他A的子类,这样使得转换后的List中的类型不统一
(2)ArrayList<A>可以转成List<A>,因为ArrayList实现了List接口
(3)List<A>也可以转成List类型,因为List是最高接口