Java进阶_04_泛型


本文介绍Java中的泛型机制。

1. 泛型概述

JDK5.0之后推出了泛型机制。在概述泛型之前,先看一下下面的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class GenericTest01 {

public static void main(String[] args) {

List myList = new ArrayList();

Animal a = new Animal();
Bird b = new Bird();
Cat c = new Cat();

myList.add(a);
myList.add(b);
myList.add(c);

Iterator it = myList.iterator();

while(it.hasNext()){
Object obj = it.next();

// 在调用具体方法的时候需要额外判断以及类型转换
if(obj instanceof Bird){
Bird tempBd = (Bird) obj;
tempBd.flying();
}else if(obj instanceof Cat){
Cat tempCt = (Cat) obj;
tempCt.eating();
}else if(obj instanceof Animal){
Animal tempAml = (Animal) obj;
tempAml.move();
}
}
}
}

class Animal{

public void move(){
System.out.println("动物在移动");
}
}

class Cat extends Animal{
public void eating(){
System.out.println("猫在吃鱼");
}
}

class Bird extends Animal{
public void flying(){
System.out.println("鸟儿在飞翔");
}
}

和前面自定义链表一样,存储的是Object类型数据,返回值也是它,这保证了存储数据类型的多样性,但是这样也带来了缺点,当我们获取集合中的元素时,返回的数据类型是Object,这时候为了进一步调用内部方法需要类型转换,此时的类型转换具有一定的繁杂。那么如何让其变得简单呢?能不能指定其返回的数据类型呢?

如果指定其返回的数据类型,那么也要指定其存储的数据类型,这就是泛型。泛型用来指定集合中存储的数据类型,集合后面只要有尖括号,就说明该类支持泛型。用了泛型之后,集合中元素的数据类型更加统一了。迭代器也可以指定泛型。使用泛型之后,迭代器每一次迭代返回的数据都是指定的类型,不再需要先强制转换再调用方法。

泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的,运行阶段泛型没用。

泛型的优点是集合中存储的元素类型统一了。从集合中取出的元素类型是泛型指定的类型,不需要进行大量的向下转型。缺点是导致集合中存储的元素缺乏多样性。大多数情况下集合中元素的类型还是统一的,所以这种特性被大家认可。

2. 泛型代码实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class GenericTest01 {

public static void main(String[] args) {

List<Animal> myList = new ArrayList<Animal>();

Animal a = new Animal();
Bird b = new Bird();
Cat c = new Cat();

myList.add(a);
myList.add(b);
myList.add(c);

Iterator<Animal> it = myList.iterator();

while(it.hasNext()){
Animal obj = it.next();
if(obj instanceof Bird){
Bird tempBd = (Bird) obj;
tempBd.flying();
}else if(obj instanceof Cat){
Cat tempCt = (Cat) obj;
tempCt.eating();
}else{
obj.move();
}
}
}
}

上述集合在创建的时候在尖括号中指明了存储的数据类型是Animal类型,此时如果向其添加其他类型数据会报错。迭代器在创建的时候指明了其返回的数据类型是Animal。此时取出的元素均为Animal类型。泛型只是在一定程度上减少了代码的复杂度。

2.1 类型自动推断

JDK8及之后引入了自动类型推断机制(也被称为钻石表达式),上面的List<Animal> myList = new ArrayList<Animal>();中ArrayList中尖括号的内容是可以省略的,即List<Animal> myList = new ArrayList<>();,这里的类型会自动推断。

3. 自定义泛型

Java支持在类型定义的时候自定义泛型。

1
2
3
4
5
6
7
8
9
10
11
12
13
class 类名<T>{
public T get(){
方法体;
}

public void doSome(T t){
方法体;
}

public T methods(T t){
方法体;
}
}

其中,尖括号中的标识符可以随便写,一般写E或者T(E是element的首字母,T是type的首字母),指明这是任意一个类型,然后在需要这个类型的方法中,写上该类型即可。在真正采用泛型的时候,会自动将指定的类型把E或者T给替换掉。如果不采用泛型,默认E或者T是Object。

4. 补充

除了上述的用法,还有<? extends ?>等用法,后续用到再追加。

5. 备注

参考B站《动力节点》。


文章作者: 浮云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 浮云 !
  目录