Java泛型
# Java泛型
# 背景
Java的泛型是在Java SE 5.0中引入的,发布时间是2004年9月。这个版本的Java引入了很多新特性,其中最重要的就是泛型。通过泛型,Java可以支持参数化类型,允许类、接口和方法在定义时使用一个或多个类型参数,从而实现更加通用、灵活和类型安全的代码。泛型也使得集合框架的设计更加简单和清晰,同时提高了代码的可读性和可维护性。
# 介绍与定义
将类型由原来的具体的类型参数化
Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
# 定义-泛型类
泛型的类参定义在类名后面用< 类参表,不同类参用逗号分隔>,如class Cname< E> class Some< E,T>
class 类名称 <泛型标识:可以随便写任意标识号,标识指定的泛型的类型>{
private 泛型标识 /*(成员变量类型)*/ var;
.....
}
}
class Point<T>{
private T t;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
以下即为一个简单例子:
// 例子
public class Box<T> {
//key这个成员变量的类型为T,T的类型由外部指定
private T t;
public void add(T t) {
this.t = t;
}
//泛型方法getKey的返回值类型为T,T的类型由外部指定
public T get() {
return t;
}
public static void main(String[] args) {
//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("教程"));
System.out.printf("整型值为 :%d\n\n", integerBox.get());
System.out.printf("字符串为 :%s\n", stringBox.get());
}
}
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
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
注意:泛型的类型参数只能是类类型,不能是简单类型。
# 定义-泛型接口
定义:接口名后加尖括号
跟普通接口类似,包含了若干需要实现类重写的抽象方法
不同的是:泛型接口指定的类参,实现类在实现接口的时候也要确保类参与接口一致即可
interface Info<T> { // 在接口上定义泛型
public T getVar(); // 定义抽象方法,抽象方法的返回值就是泛型类型
public void setVar(T x);
}
1
2
3
4
2
3
4
# 定义-泛型方法
下面是定义泛型方法的规则跟一些注意点:
- 用
<类参符号>
在方法返回类型之前定义,类参符号一般用一个大写字母表示即可 - 类参符号表中类参可以是多个,中间用逗号来分隔,比如<E,T>
- 泛型在编译时,效率是低下的,在运行时才能确定T的具体类型
- T代表任意的引用类型,但不能是基本类型
- 泛型方法中的T只对当前方法有效,不能影响其它方法
- **注意:**这种 public T setX(){ } 不是泛型方法 它只是使用了泛型类中的泛型
/**
* 泛型方法的基本介绍
* @param tClass 传入的泛型实参
* @return T 返回值为T类型
* 说明:
* 1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
* 2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
* 3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
* 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
*/
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
IllegalAccessException{
T instance = tClass.newInstance();
return instance;
}
// 参数如果是多个,在public和返回值的中间写
public <T,K> K showKeyName(Generic<T> container){
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 泛型通配符
类型通配符一般是使用 ? 代替具体的类型参数。
例如 List<?> 在逻辑上是 List<String>,List<Integer> 等所有 List<具体类型实参> 的父类。
import java.util.*;
public class GenericTest {
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(List<?> data) {
System.out.println("data :" + data.get(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
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
输出结果:
data :icon
data :18
data :314
1
2
3
2
3
上次更新: 2024/12/01, 14:58:26