前言

Java泛型(Generics)是Java 5引入的重要特性,它提供了编译时的类型安全检查,消除了类型转换的需要,并支持泛型算法的实现。泛型不仅提高了代码的可读性和可维护性,还大大减少了运行时错误的可能性。本文将深入探讨Java泛型的核心概念、语法规则、高级特性以及实际应用场景。

泛型概述与基本概念

泛型的定义与优势

泛型允许在定义类、接口和方法时使用类型参数,这些参数在使用时会被具体的类型替换。

graph TD
    A[Java泛型] --> B[类型安全]
    A --> C[消除类型转换]
    A --> D[代码重用]
    A --> E[编译时检查]
    
    B --> F[编译期类型检查]
    B --> G[避免ClassCastException]
    
    C --> H[自动类型推断]
    C --> I[减少强制转换]
    
    D --> J[泛型类]
    D --> K[泛型接口]
    D --> L[泛型方法]
    
    E --> M[早期发现错误]
    E --> N[提高代码质量]

泛型前后的对比

Java 5之前的集合使用

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
public class PreGenericsExample {
public void demonstrateOldStyle() {
// 没有泛型的List
List list = new ArrayList();
list.add("字符串");
list.add(123); // 可以添加任意类型
list.add(new Date()); // 没有编译时检查

// 需要强制类型转换,容易出错
for (int i = 0; i < list.size(); i++) {
String str = (String) list.get(i); // ClassCastException风险
System.out.println(str.toUpperCase());
}
}

public void demonstrateUnsafeOperations() {
Map map = new HashMap();
map.put("name", "张三");
map.put("age", 25);
map.put(123, "数字键"); // 类型不一致

// 获取值时需要强制转换
String name = (String) map.get("name");
Integer age = (Integer) map.get("age"); // 潜在的类型转换异常

System.out.println("姓名: " + name + ", 年龄: " + age);
}
}

Java 5+的泛型使用

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
public class GenericsExample {
public void demonstrateNewStyle() {
// 使用泛型的List
List<String> stringList = new ArrayList<>();
stringList.add("字符串");
// stringList.add(123); // 编译错误!
// stringList.add(new Date()); // 编译错误!

// 不需要强制类型转换
for (String str : stringList) {
System.out.println(str.toUpperCase());
}
}

public void demonstrateSafeOperations() {
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 25);
// map.put(123, "数字键"); // 编译错误!键必须是String类型

// 类型安全的获取
String name = (String) map.get("name");
Integer age = (Integer) map.get("age");

System.out.println("姓名: " + name + ", 年龄: " + age);
}
}

泛型类与泛型接口

泛型类的定义和使用

graph LR
    A[泛型类定义] --> B[类型参数声明]
    B --> C["class ClassName"]
    
    A --> D[类型参数使用]
    D --> E[成员变量类型]
    D --> F[方法参数类型]
    D --> G[方法返回类型]
    
    A --> H[类型参数约束]
    H --> I[""]
    H --> J[""]
    H --> K[""]

基本泛型类实现

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* 泛型容器类示例
* @param <T> 元素类型参数
*/
public class GenericContainer<T> {
private T item;
private List<T> items;

public GenericContainer() {
this.items = new ArrayList<>();
}

public GenericContainer(T item) {
this();
this.item = item;
}

// 设置单个元素
public void setItem(T item) {
this.item = item;
}

// 获取单个元素
public T getItem() {
return item;
}

// 添加元素到列表
public void addItem(T item) {
items.add(item);
}

// 获取指定索引的元素
public T getItem(int index) {
if (index >= 0 && index < items.size()) {
return items.get(index);
}
return null;
}

// 获取所有元素
public List<T> getAllItems() {
return new ArrayList<>(items);
}

// 获取元素数量
public int size() {
return items.size();
}

// 检查是否为空
public boolean isEmpty() {
return items.isEmpty();
}

// 清空所有元素
public void clear() {
item = null;
items.clear();
}

@Override
public String toString() {
return "GenericContainer{" +
"item=" + item +
", items=" + items +
'}';
}
}

多类型参数的泛型类

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
53
54
55
56
/**
* 键值对泛型类
* @param <K> 键的类型
* @param <V> 值的类型
*/
public 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 void setKey(K key) {
this.key = key;
}

public V getValue() {
return value;
}

public void setValue(V value) {
this.value = value;
}

// 交换键值
public Pair<V, K> swap() {
return new Pair<>(value, key);
}

// 类型安全的equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;

Pair<?, ?> pair = (Pair<?, ?>) obj;
return Objects.equals(key, pair.key) &&
Objects.equals(value, pair.value);
}

@Override
public int hashCode() {
return Objects.hash(key, value);
}

@Override
public String toString() {
return "Pair{" + key + " -> " + 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class GenericClassUsage {
public void demonstrateGenericContainer() {
// 字符串容器
GenericContainer<String> stringContainer = new GenericContainer<>();
stringContainer.addItem("第一个字符串");
stringContainer.addItem("第二个字符串");
stringContainer.setItem("当前字符串");

System.out.println("字符串容器: " + stringContainer);
System.out.println("当前项: " + stringContainer.getItem());
System.out.println("第一个项: " + stringContainer.getItem(0));

// 整数容器
GenericContainer<Integer> intContainer = new GenericContainer<>(100);
intContainer.addItem(200);
intContainer.addItem(300);

System.out.println("整数容器: " + intContainer);

// 自定义对象容器
GenericContainer<Person> personContainer = new GenericContainer<>();
personContainer.addItem(new Person("张三", 25));
personContainer.addItem(new Person("李四", 30));

for (int i = 0; i < personContainer.size(); i++) {
Person person = personContainer.getItem(i);
System.out.println("人员 " + i + ": " + person);
}
}

public void demonstratePairUsage() {
// 字符串-整数对
Pair<String, Integer> nameAge = new Pair<>("张三", 25);
System.out.println("姓名年龄对: " + nameAge);

// 交换键值
Pair<Integer, String> ageNameswap = nameAge.swap();
System.out.println("交换后: " + ageNameswap);

// 坐标对
Pair<Double, Double> coordinate = new Pair<>(3.14, 2.71);
System.out.println("坐标: (" + coordinate.getKey() +
", " + coordinate.getValue() + ")");

// 配置对
Pair<String, String> config = new Pair<>("database.url",
"jdbc:mysql://localhost:3306/test");
System.out.println("配置: " + config);
}

// 简单的Person类
static class Person {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
}
}

泛型接口

泛型接口定义

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
/**
* 泛型比较器接口
*/
public interface GenericComparator<T> {
int compare(T o1, T o2);
boolean equals(T o1, T o2);

// 默认方法
default boolean isLess(T o1, T o2) {
return compare(o1, o2) < 0;
}

default boolean isGreater(T o1, T o2) {
return compare(o1, o2) > 0;
}
}

/**
* 泛型数据访问接口
*/
public interface GenericDao<T, ID> {
void save(T entity);
T findById(ID id);
List<T> findAll();
void update(T entity);
void deleteById(ID id);
boolean existsById(ID id);
}

泛型接口实现

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
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 字符串比较器实现
*/
public class StringComparator implements GenericComparator<String> {
@Override
public int compare(String o1, String o2) {
if (o1 == null && o2 == null) return 0;
if (o1 == null) return -1;
if (o2 == null) return 1;
return o1.compareToIgnoreCase(o2);
}

@Override
public boolean equals(String o1, String o2) {
return compare(o1, o2) == 0;
}
}

/**
* 用户数据访问实现
*/
public class UserDao implements GenericDao<User, Long> {
private List<User> users = new ArrayList<>();
private long nextId = 1;

@Override
public void save(User entity) {
if (entity.getId() == null) {
entity.setId(nextId++);
}
users.add(entity);
}

@Override
public User findById(Long id) {
return users.stream()
.filter(user -> Objects.equals(user.getId(), id))
.findFirst()
.orElse(null);
}

@Override
public List<User> findAll() {
return new ArrayList<>(users);
}

@Override
public void update(User entity) {
User existing = findById(entity.getId());
if (existing != null) {
int index = users.indexOf(existing);
users.set(index, entity);
}
}

@Override
public void deleteById(Long id) {
users.removeIf(user -> Objects.equals(user.getId(), id));
}

@Override
public boolean existsById(Long id) {
return findById(id) != null;
}
}

泛型方法

泛型方法可以在普通类中定义,也可以在泛型类中定义,它们有自己的类型参数。

泛型方法的定义语法

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
public class GenericMethods {

// 泛型方法:交换数组中两个元素的位置
public static <T> void swap(T[] array, int i, int j) {
if (array == null || i < 0 || j < 0 ||
i >= array.length || j >= array.length) {
throw new IllegalArgumentException("无效的参数");
}
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}

// 泛型方法:查找数组中指定元素的索引
public static <T> int indexOf(T[] array, T target) {
if (array == null) return -1;

for (int i = 0; i < array.length; i++) {
if (Objects.equals(array[i], target)) {
return i;
}
}
return -1;
}

// 泛型方法:创建填充指定值的列表
public static <T> List<T> createFilledList(T value, int count) {
List<T> list = new ArrayList<>();
for (int i = 0; i < count; i++) {
list.add(value);
}
return list;
}

// 泛型方法:安全的类型转换
@SuppressWarnings("unchecked")
public static <T> T safeCast(Object obj, Class<T> type) {
if (obj == null) {
return null;
}
if (type.isInstance(obj)) {
return (T) obj;
}
throw new ClassCastException("无法将 " + obj.getClass() +
" 转换为 " + type);
}

// 多类型参数的泛型方法
public static <K, V> Map<K, V> createMap(K[] keys, V[] values) {
if (keys == null || values == null || keys.length != values.length) {
throw new IllegalArgumentException("键和值数组长度必须相等");
}

Map<K, V> map = new HashMap<>();
for (int i = 0; i < keys.length; i++) {
map.put(keys[i], values[i]);
}
return map;
}

// 有界的泛型方法
public static <T extends Number> double sum(List<T> numbers) {
if (numbers == null || numbers.isEmpty()) {
return 0.0;
}

double total = 0.0;
for (T number : numbers) {
if (number != null) {
total += number.doubleValue();
}
}
return total;
}

// 演示泛型方法的使用
public static void demonstrateGenericMethods() {
// 测试swap方法
String[] names = {"Alice", "Bob", "Charlie"};
System.out.println("交换前: " + Arrays.toString(names));
swap(names, 0, 2);
System.out.println("交换后: " + Arrays.toString(names));

// 测试indexOf方法
Integer[] numbers = {1, 2, 3, 4, 5};
int index = indexOf(numbers, 3);
System.out.println("数字3的索引: " + index);

// 测试createFilledList方法
List<String> filledList = createFilledList("Hello", 3);
System.out.println("填充列表: " + filledList);

// 测试safeCast方法
Object obj = "这是一个字符串";
String str = safeCast(obj, String.class);
System.out.println("安全转换: " + str);

// 测试createMap方法
String[] keys = {"name", "age", "city"};
Object[] values = {"张三", 25, "北京"};
Map<String, Object> map = createMap(keys, values);
System.out.println("创建的映射: " + map);

// 测试sum方法
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
double sum = sum(intList);
System.out.println("数字和: " + sum);
}
}

通配符与边界

Java泛型中的通配符提供了更灵活的类型匹配机制。

graph TD
    A[通配符类型] --> B[无界通配符 ?]
    A --> C[上界通配符 ? extends T]
    A --> D[下界通配符 ? super T]
    
    B --> E[可以接受任何类型]
    B --> F[只能读取Object]
    B --> G[不能写入除null外的值]
    
    C --> H[接受T及其子类]
    C --> I[支持协变读取]
    C --> J[不支持写入]
    
    D --> K[接受T及其父类]
    D --> L[支持逆变写入]
    D --> M[读取返回Object]

无界通配符(?)

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
public class UnboundedWildcards {

// 打印任意类型的列表
public static void printList(List<?> list) {
for (Object item : list) {
System.out.println(item);
}
}

// 获取列表大小(适用于任何类型)
public static int getListSize(List<?> list) {
return list != null ? list.size() : 0;
}

// 检查列表是否为空
public static boolean isEmpty(Collection<?> collection) {
return collection == null || collection.isEmpty();
}

// 清空任意类型的集合
public static void clearCollection(Collection<?> collection) {
if (collection != null) {
collection.clear();
}
}

public static void demonstrateUnboundedWildcards() {
List<String> stringList = Arrays.asList("A", "B", "C");
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);

System.out.println("字符串列表:");
printList(stringList);

System.out.println("整数列表:");
printList(intList);

System.out.println("双精度列表:");
printList(doubleList);

System.out.println("列表大小: " + getListSize(stringList));
System.out.println("是否为空: " + isEmpty(intList));
}
}

上界通配符(? extends 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
public class UpperBoundedWildcards {

// 计算数字列表的和
public static double calculateSum(List<? extends Number> numbers) {
double sum = 0.0;
for (Number num : numbers) {
if (num != null) {
sum += num.doubleValue();
}
}
return sum;
}

// 查找数字列表中的最大值
public static double findMax(List<? extends Number> numbers) {
if (numbers == null || numbers.isEmpty()) {
throw new IllegalArgumentException("列表不能为空");
}

double max = Double.NEGATIVE_INFINITY;
for (Number num : numbers) {
if (num != null) {
max = Math.max(max, num.doubleValue());
}
}
return max;
}

// 复制扩展了某个类型的列表
public static <T> void copyList(List<? extends T> source, List<T> destination) {
destination.clear();
for (T item : source) {
destination.add(item);
}
}

// 处理形状列表(假设有Shape基类)
public static void processShapes(List<? extends Shape> shapes) {
System.out.println("处理形状列表:");
for (Shape shape : shapes) {
System.out.println("- " + shape.getClass().getSimpleName() +
": 面积 = " + shape.getArea());
}
}

public static void demonstrateUpperBoundedWildcards() {
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
List<Float> floatList = Arrays.asList(1.0f, 2.0f, 3.0f);

System.out.println("整数列表和: " + calculateSum(intList));
System.out.println("双精度列表和: " + calculateSum(doubleList));
System.out.println("浮点列表和: " + calculateSum(floatList));

System.out.println("整数列表最大值: " + findMax(intList));
System.out.println("双精度列表最大值: " + findMax(doubleList));

// 形状处理示例
List<Circle> circles = Arrays.asList(
new Circle(5), new Circle(3), new Circle(7)
);
processShapes(circles);
}

// 简单的形状类层次结构
abstract static class Shape {
public abstract double getArea();
}

static class Circle extends Shape {
private double radius;

public Circle(double radius) {
this.radius = radius;
}

@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
}

下界通配符(? super 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class LowerBoundedWildcards {

// 向列表中添加元素(可以是T或T的子类)
public static <T> void addElements(List<? super T> list, T... elements) {
for (T element : elements) {
list.add(element);
}
}

// 将子类型列表的元素添加到父类型列表中
public static <T> void addAll(List<? super T> destination,
List<? extends T> source) {
for (T item : source) {
destination.add(item);
}
}

// 比较器示例:可以比较T或T的父类
public static <T> void sortList(List<T> list,
Comparator<? super T> comparator) {
list.sort(comparator);
}

// 使用下界通配符的实用工具方法
public static <T> void fill(List<? super T> list, T value, int count) {
list.clear();
for (int i = 0; i < count; i++) {
list.add(value);
}
}

public static void demonstrateLowerBoundedWildcards() {
// 创建不同类型的列表
List<Object> objectList = new ArrayList<>();
List<Number> numberList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();

// 向Object列表添加各种类型的元素
addElements(objectList, "字符串", 123, 3.14, true);
System.out.println("Object列表: " + objectList);

// 向Number列表添加数字
addElements(numberList, 1, 2.5, 3.14f);
System.out.println("Number列表: " + numberList);

// 将Integer列表的元素添加到Number列表
integerList.addAll(Arrays.asList(10, 20, 30));
addAll(numberList, integerList);
System.out.println("合并后的Number列表: " + numberList);

// 使用比较器排序
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9);
System.out.println("排序前: " + numbers);

// 使用Number的比较器来排序Integer列表
Comparator<Number> numberComparator = (n1, n2) ->
Double.compare(n1.doubleValue(), n2.doubleValue());
sortList(numbers, numberComparator);
System.out.println("排序后: " + numbers);

// 填充列表
List<Number> filledList = new ArrayList<>();
fill(filledList, 42, 5);
System.out.println("填充的列表: " + filledList);
}
}

类型擦除与限制

Java泛型使用类型擦除机制实现,这带来了一些限制和需要注意的地方。

类型擦除机制

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
53
public class TypeErasure {

// 编译后这两个方法会有相同的签名,导致编译错误
// public void process(List<String> list) { }
// public void process(List<Integer> list) { } // 编译错误

// 正确的重载方式
public void processStrings(List<String> list) {
System.out.println("处理字符串列表: " + list);
}

public void processIntegers(List<Integer> list) {
System.out.println("处理整数列表: " + list);
}

// 演示类型擦除的影响
public void demonstrateTypeErasure() {
List<String> stringList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();

// 运行时类型信息相同
System.out.println("String列表类型: " + stringList.getClass());
System.out.println("Integer列表类型: " + intList.getClass());
System.out.println("类型相同: " +
(stringList.getClass() == intList.getClass()));

// 无法在运行时获取泛型参数类型
// if (stringList instanceof List<String>) { } // 编译错误
if (stringList instanceof List<?>) { // 正确的方式
System.out.println("stringList是List的实例");
}
}

// 泛型数组的限制
public void demonstrateGenericArrayLimitations() {
// 无法创建泛型数组
// List<String>[] arrays = new List<String>[10]; // 编译错误

// 可以使用通配符
List<?>[] arrays = new List<?>[10];
arrays[0] = Arrays.asList("a", "b", "c");
arrays[1] = Arrays.asList(1, 2, 3);

System.out.println("通配符数组: " + Arrays.toString(arrays));

// 使用ArrayList代替数组
List<List<String>> listOfLists = new ArrayList<>();
listOfLists.add(Arrays.asList("第一个列表"));
listOfLists.add(Arrays.asList("第二个列表"));

System.out.println("列表的列表: " + listOfLists);
}
}

泛型的限制和解决方案

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public class GenericLimitations {

// 无法使用基本类型作为类型参数
// List<int> intList; // 编译错误,应该使用Integer

// 无法创建类型参数的实例
public class GenericClass<T> {
// private T instance = new T(); // 编译错误

// 解决方案:使用反射
private Class<T> type;

public GenericClass(Class<T> type) {
this.type = type;
}

public T createInstance() throws Exception {
return type.getDeclaredConstructor().newInstance();
}
}

// 无法创建类型参数的数组
public class GenericArrayHandler<T> {
// private T[] array = new T[10]; // 编译错误

private T[] array;

@SuppressWarnings("unchecked")
public GenericArrayHandler(Class<T> type, int size) {
// 使用反射创建数组
array = (T[]) Array.newInstance(type, size);
}

public void set(int index, T value) {
array[index] = value;
}

public T get(int index) {
return array[index];
}

public T[] getArray() {
return Arrays.copyOf(array, array.length);
}
}

// 静态上下文中的泛型限制
public class StaticGenericLimitations<T> {
// 静态字段不能使用类的类型参数
// private static T staticField; // 编译错误

private static <U> U staticMethod(U param) {
return param; // 可以使用自己的类型参数
}

// 静态内部类不能访问外部类的类型参数
static class StaticInnerClass {
// private T field; // 编译错误
}
}

public void demonstrateLimitations() {
try {
// 使用反射创建泛型实例
GenericClass<String> stringClass = new GenericClass<>(String.class);
String instance = stringClass.createInstance();
System.out.println("创建的实例: " + instance);

// 使用泛型数组处理器
GenericArrayHandler<Integer> intHandler =
new GenericArrayHandler<>(Integer.class, 5);
intHandler.set(0, 10);
intHandler.set(1, 20);
System.out.println("数组元素: " + intHandler.get(0) + ", " + intHandler.get(1));

} catch (Exception e) {
System.err.println("创建实例失败: " + e.getMessage());
}
}
}

实际应用案例

泛型工具类设计

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* 泛型响应结果封装类
*/
public class Result<T> {
private boolean success;
private String message;
private T data;
private int code;

private Result(boolean success, String message, T data, int code) {
this.success = success;
this.message = message;
this.data = data;
this.code = code;
}

// 成功结果
public static <T> Result<T> success(T data) {
return new Result<>(true, "操作成功", data, 200);
}

public static <T> Result<T> success(String message, T data) {
return new Result<>(true, message, data, 200);
}

// 失败结果
public static <T> Result<T> failure(String message) {
return new Result<>(false, message, null, 500);
}

public static <T> Result<T> failure(String message, int code) {
return new Result<>(false, message, null, code);
}

// Getter方法
public boolean isSuccess() { return success; }
public String getMessage() { return message; }
public T getData() { return data; }
public int getCode() { return code; }

@Override
public String toString() {
return String.format("Result{success=%s, message='%s', data=%s, code=%d}",
success, message, data, code);
}
}

/**
* 泛型缓存管理器
*/
public class CacheManager<K, V> {
private final Map<K, CacheEntry<V>> cache;
private final long defaultTtl;

public CacheManager(long defaultTtl) {
this.cache = new ConcurrentHashMap<>();
this.defaultTtl = defaultTtl;
}

public void put(K key, V value) {
put(key, value, defaultTtl);
}

public void put(K key, V value, long ttl) {
long expireTime = System.currentTimeMillis() + ttl;
cache.put(key, new CacheEntry<>(value, expireTime));
}

public V get(K key) {
CacheEntry<V> entry = cache.get(key);
if (entry == null) {
return null;
}

if (entry.isExpired()) {
cache.remove(key);
return null;
}

return entry.getValue();
}

public boolean containsKey(K key) {
return get(key) != null;
}

public void remove(K key) {
cache.remove(key);
}

public void clear() {
cache.clear();
}

public int size() {
// 清理过期条目
clearExpired();
return cache.size();
}

private void clearExpired() {
Iterator<Map.Entry<K, CacheEntry<V>>> iterator = cache.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<K, CacheEntry<V>> entry = iterator.next();
if (entry.getValue().isExpired()) {
iterator.remove();
}
}
}

private static class CacheEntry<V> {
private final V value;
private final long expireTime;

public CacheEntry(V value, long expireTime) {
this.value = value;
this.expireTime = expireTime;
}

public V getValue() {
return value;
}

public boolean isExpired() {
return System.currentTimeMillis() > expireTime;
}
}
}

实际应用演示

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
public class GenericApplicationDemo {

public void demonstrateResultUsage() {
// 用户服务示例
UserService userService = new UserService();

// 成功情况
Result<User> userResult = userService.getUserById(1L);
if (userResult.isSuccess()) {
User user = userResult.getData();
System.out.println("获取用户成功: " + user);
}

// 失败情况
Result<User> notFoundResult = userService.getUserById(999L);
if (!notFoundResult.isSuccess()) {
System.out.println("获取用户失败: " + notFoundResult.getMessage());
}

// 列表结果
Result<List<User>> usersResult = userService.getAllUsers();
if (usersResult.isSuccess()) {
List<User> users = usersResult.getData();
System.out.println("获取用户列表成功,共 " + users.size() + " 个用户");
}
}

public void demonstrateCacheUsage() {
// 创建字符串缓存
CacheManager<String, String> stringCache = new CacheManager<>(5000); // 5秒TTL

stringCache.put("user:1", "张三");
stringCache.put("user:2", "李四");

System.out.println("缓存大小: " + stringCache.size());
System.out.println("用户1: " + stringCache.get("user:1"));

// 创建对象缓存
CacheManager<Long, User> userCache = new CacheManager<>(10000); // 10秒TTL

userCache.put(1L, new User(1L, "张三", "zhang@email.com"));
userCache.put(2L, new User(2L, "李四", "li@email.com"));

User cachedUser = userCache.get(1L);
if (cachedUser != null) {
System.out.println("从缓存获取用户: " + cachedUser);
}

// 等待过期测试
try {
Thread.sleep(6000); // 等待6秒
String expiredValue = stringCache.get("user:1");
System.out.println("过期后的值: " + expiredValue); // 应该为null
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

// 模拟用户服务
static class UserService {
private List<User> users = Arrays.asList(
new User(1L, "张三", "zhang@email.com"),
new User(2L, "李四", "li@email.com"),
new User(3L, "王五", "wang@email.com")
);

public Result<User> getUserById(Long id) {
User user = users.stream()
.filter(u -> u.getId().equals(id))
.findFirst()
.orElse(null);

if (user != null) {
return Result.success(user);
} else {
return Result.failure("用户不存在", 404);
}
}

public Result<List<User>> getAllUsers() {
return Result.success("获取用户列表成功", users);
}
}

// 用户实体类
static class User {
private Long id;
private String name;
private String email;

public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}

// Getter方法
public Long getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }

@Override
public String toString() {
return String.format("User{id=%d, name='%s', email='%s'}", id, name, email);
}
}
}

总结

Java泛型是一个强大而重要的特性,它提供了类型安全、代码重用和性能优化等诸多优势。通过本文的学习,我们深入了解了:

  1. 泛型基础:理解了泛型的概念、优势和基本语法
  2. 泛型类与接口:掌握了如何定义和使用泛型类和接口
  3. 泛型方法:学会了定义灵活的泛型方法
  4. 通配符机制:理解了上界、下界和无界通配符的使用场景
  5. 类型擦除:了解了Java泛型的实现机制和相关限制
  6. 实际应用:通过实例展示了泛型在实际开发中的应用

掌握Java泛型对于编写类型安全、可维护的代码至关重要。在实际开发中,合理使用泛型不仅能提高代码质量,还能提升开发效率。建议开发者:

  • 优先使用泛型集合而不是原始类型
  • 合理设计泛型API以提高代码重用性
  • 理解通配符的使用场景,避免类型转换错误
  • 注意泛型的限制,选择合适的设计方案
  • 在团队开发中制定一致的泛型使用规范

通过不断实践和应用,您将能够更加熟练地使用Java泛型,编写出更加优雅和健壮的代码。

参考资料