05.泛型
# 01.泛型
- 泛型允许在类、接口和方法的定义中使用类型参数
- 其主要目的是提供编译时类型安全检查和消除手动类型转换的需要,从而使代码更易于阅读和写作
# 1、集合类
- 可以创建一个只能包含字符串的ArrayList对象:
ArrayList<String> list = new ArrayList<String>();
- 这样,编译器就会确保只有字符串被添加到list中,否则编译错误
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] strings) {
// 原始类型的List,它可以接受任何类型的对象,编译器无法检查(会报警告)
// List list = new ArrayList();
// 消除此警告,您需要使用Java泛型来指定List中元素的类型
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
System.out.println(list);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2、自定义类或方法
- 在这个类中,K和V分别代表键和值的类型,使用这个泛型类,我们可以创建不同类型的键值对
- 例如
- 我们可以创建一个键和值都是Integer类型的Pair对象
- 也可以创建一个键是String类型,值是Integer类型的Pair对象
public class Test {
public static void main(String[] strings) {
// 创建一个键和值都是Integer类型的Pair对象
Pair<Integer, Integer> pair1 = new Pair<>(1, 2);
System.out.println("Key: " + pair1.getKey() + ", Value: " + pair1.getValue());
// 创建一个键是String类型,值是Integer类型的Pair对象
Pair<String, Integer> pair2 = new Pair<>("One", 1);
System.out.println("Key: " + pair2.getKey() + ", Value: " + pair2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
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
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
# 3、泛型方法
- 我们定义了一个名为
printAndReturn
的泛型方法,它接受一个类型为T的参数,并返回一个相同类型的结果 - 在这个例子中,
printAndReturn
方法可以接受任何类型的参数,并返回与输入相同类型的结果 - 在
main
方法中,我们分别用String,Integer和自定义类型Student来调用printAndReturn
方法 - 这就体现了泛型在方法上的使用可以增加方法的灵活性,提高代码的可重用性
public class Test {
public static <T> T printAndReturn(T element123) {
System.out.println(">>> " + element123);
return element123;
}
public static void main(String[] args) {
// 使用String类型调用泛型方法
String str = printAndReturn("Hello World");
System.out.println("Returned: " + str);
// 使用Integer类型调用泛型方法
Integer i = printAndReturn(123);
System.out.println("Returned: " + i);
// 使用自定义类型Student调用泛型方法
Student s = new Student("Tom", 90);
Student returnedStudent = printAndReturn(s);
System.out.println("Returned: " + returnedStudent.getName());
}
// 定义一个简单的Student类用于测试
static class Student {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
}
}
/*
>>> Hello World
Returned: Hello World
>>> 123
Returned: 123
>>> cls.Test$Student@4517d9a3
Returned: Tom
*/
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
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
# 4、 extends通配符
- "extends"关键字用于限制泛型类型必须是某个类,或者是其子类
- 它可以帮助我们在编译时期进行类型检查,保证程序的类型安全
- 下面这个Box类表示,我们可以创建一个包含Number或者Number的子类的Box,如
Box<Integer>
,Box<Float>
- 但是不能创建一个包含不是Number或其子类的Box,比如
Box<String>
,否则编译器会报错
public class Test {
public static void main(String[] strings) {
// 创建一个Box<Integer>对象
Box<Integer> integerBox = new Box<>();
integerBox.set(123);
System.out.println("Integer Box: " + integerBox.get());
// 创建一个Box<Float>对象
Box<Float> floatBox = new Box<>();
floatBox.set(123.456f);
System.out.println("Float Box: " + floatBox.get());
// 下面的代码将会编译错误,因为String不是Number的子类
// Box<String> stringBox = new Box<>();
// stringBox.set("Hello World");
}
}
// 我们可以创建一个包含Number或者Number的子类的Box,如`Box<Integer>`,`Box<Float>`
class Box<T extends Number> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
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
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
# 5、super通配符
- "super"指你可以传递给泛型方法的参数类型可以是指定的类型,或者是这个类型的父类型,而不是子类型
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Animal> animals = new ArrayList<>();
animals.add(new Animal());
animals.add(new Mammal());
animals.add(new Dog());
process(animals); // 这是合法的,因为Animal是Mammal的父类
// 下面的代码将会编译错误,因为Dog是Mammal的子类,不满足<? super Mammal>的要求
// List<Dog> dogs = new ArrayList<>();
// dogs.add(new Dog());
// process(dogs);
}
public static void process(List<? super Mammal> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
}
class Animal {
@Override
public String toString() {
return "I am an Animal.";
}
}
class Mammal extends Animal {
@Override
public String toString() {
return "I am a Mammal.";
}
}
class Dog extends Mammal {
@Override
public String toString() {
return "I am a Dog.";
}
}
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
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
上次更新: 2024/5/31 11:18:42