十四 泛型----参数化类型
思考:常规的类和方法使用的类型无非分为两类:基本类型和类,如何编写一个更具通用性的类或方法来使用多种类型呢?
无力的多态
当把基类或接口作为参数类型,则可以接受所有继承基类或者实现接口的导出类作为参数。如此达到了一定的通用性的效果。但是即使如此还是局限性很强,一旦我们确定了基类或者接口以后我们的参数就必须为继承或实现的类型信息。当要求我们的代码能够应用于某种不确定不具体的类型而不是具体的基类或者接口的时候,多态就显得如此无力!
泛型
概念:参数化类型。犹如平时我们使用带参的方法一般:定义的时候将类型定义为类型形参,在调用时传入具体的类型实参,本质就是在不创建新类的条件下,通过泛型指定不同的类型来控制类型形参的具体类型。当被操作的类型的限制条件出现在类、接口、方法中时,分别称为泛型类、泛型接口、泛型方法。
作用:代码可以应用于多种类型。当然也能保证我们的容器持有相同类型的对象,同时在调用之前都已经确定了对象类型避免了强制类型转换。
图1
图2
输出:
Animal.name:jack Animal.age:10
Human.name:selina Human.age:1
jack love selina
1314
图3
如上三图即可简单说明泛型的重要性,以及简单泛型的实现原理以及作用。图一和图二主要是说了多态类型的局限性。图三展现了既能不限制代码应用于多种类型的同时又能保证吃有统一类型的优良特性。
泛型的使用
三种方式:泛型类、泛型接口、泛型方法
1泛型类
各种容器类为代表包括List、Set、Map,泛型类的写法如下,当然我如上写的Holder类就一个自定义泛型类,如何写自定义发型类,以及其中字母的含义又是什么呢?
泛型字母
- 形式类型参数(formal type parameters)即泛型字母
-
命名泛型字母可以随意指定,尽量使用单个的大写字母(有时候多个泛型类型时会加上数字,比如T1,T2)
常见字母(见名知意)- T Type
- K V Key Value
- E Element
- 当类被使用时,会使用具体的实际类型参数代替
注意:泛型类的类型只能用在成员变量上,只能使用引用类型
public class Holder3<T>{
//此处a的类型有T外部指定,此处的a为成员变量而且是引用类型
private T a;
public Holder3(T a) {
this.a = a;
}
public T getT() {
return a;
}
public void setT(T a) {
this.a = a;
}
}
泛型继承
/**
* 泛型继承
*
* 保留父类泛型 ----》泛型子类
* 不保留父类泛型 -----》子类按需实现
*
* 子类重写父类的方法,泛型类型随父类而定 子类使用父类的属性,该属性类型随父类定义的泛型
*
* @author Administrator
*
* @param <T1>
* @param <T2>
*/
public abstract class Father<T1, T2> {
T1 age;
public abstract void test(T2 name);
}
// 保留父类泛型 ----》泛型子类
// 1)全部保留
class C1<T1, T2> extends Father<T1, T2> {
@Override
public void test(T2 name) {
}
}
// 2) 部分保留
class C2<T1> extends Father<T1, Integer> {
@Override
public void test(Integer name) {
}
}
// 不保留父类泛型 -----》子类按需实现
// 1)具体类型
class C3 extends Father<String, Integer> {
@Override
public void test(Integer name) {
}
}
// 2)没有具体类型
// 泛型擦除:实现或继承父类的子类,没有指定类型,类似于Object
class C4 extends Father {
@Override
public void test(Object name) {
}
}
2泛型接口
注意:接口中的泛型只能用在抽象方法上,不能用于变量上。
在List接口中采用泛型化定义之后,<E>中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。
public interface List<E> extends Collection<E> {
2
3 int size();
4
5 boolean isEmpty();
6
7 boolean contains(Object o);
8
9 Iterator<E> iterator();
10
11 Object[] toArray();
12
13 <T> T[] toArray(T[] a);
14
15 boolean add(E e);
16
17 boolean remove(Object o);
18
19 boolean containsAll(Collection<?> c);
20
21 boolean addAll(Collection<? extends E> c);
22
23 boolean addAll(int index, Collection<? extends E> c);
24
25 boolean removeAll(Collection<?> c);
26
27 boolean retainAll(Collection<?> c);
28
29 void clear();
30
31 boolean equals(Object o);
32
33 int hashCode();
34
35 E get(int index);
36
37 E set(int index, E element);
38
39 void add(int index, E element);
40
41 E remove(int index);
42
43 int indexOf(Object o);
44
45 int lastIndexOf(Object o);
46
47 ListIterator<E> listIterator();
48
49 ListIterator<E> listIterator(int index);
50
51 List<E> subList(int fromIndex, int toIndex);
52 }
巨人的肩膀:
1)java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一:https://blog.csdn.net/s10461/article/details/53941091
2)Java总结篇系列:Java泛型:https://www.cnblogs.com/lwbqqyumidi/p/3837629.html
3)Java知识点总结(Java泛型):https://segmentfault.com/a/1190000014824002