一、泛型概述
泛型是Java 5引入的核心语言特性,在JDK1.8中得到了全面支持和增强。泛型实现了参数化类型的概念,使代码能够在不指定具体类型的情况下工作,同时保证了类型安全。泛型的核心价值在于:
- 类型安全:编译时检查类型错误
- 代码复用:一套代码可适用于多种类型
- 消除强制转换:减少运行时ClassCastException风险
二、JDK1.8中泛型的五种使用方式
1. 泛型类
泛型类是最基本的泛型使用形式,通过在类声明时指定类型参数实现。
// 典型泛型类示例
public class Response<T> {
private int code;
private String message;
private T data; // 泛型字段
public Response(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
// 泛型返回值
public T getData() {
return data;
}
// 泛型方法(虽然类已经是泛型类)
public <E> void logData(E additionalInfo) {
System.out.println("Data: " + data + ", Info: " + additionalInfo);
}
}
// 使用示例
Response<User> userResponse = new Response<>(200, "Success", new User("Alice"));
User user = userResponse.getData(); // 无需类型转换
2. 泛型接口
泛型接口广泛应用于各种函数式接口和集合类中。
// 自定义泛型接口示例
public interface Transformer<T, R> {
R transform(T input);
// JDK1.8默认方法也可以使用泛型
default <V> Transformer<T, V> andThen(Transformer<R, V> after) {
return input -> after.transform(transform(input));
}
}
// 使用示例
Transformer<String, Integer> stringToInt = Integer::valueOf;
Transformer<Integer, String> intToHex = i -> Integer.toHexString(i);
// 使用方法组合
Transformer<String, String> chain = stringToInt.andThen(intToHex);
String result = chain.transform("255"); // 输出"ff"
3. 泛型方法
泛型方法可以在非泛型类中定义,方法自己声明类型参数。
public class CollectionUtils {
// 静态泛型方法
public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
return list.stream()
.filter(predicate)
.collect(Collectors.toList());
}
// 泛型可变参数
@SafeVarargs
public static <T> List<T> mergeLists(List<T>... lists) {
return Arrays.stream(lists)
.flatMap(List::stream)
.collect(Collectors.toList());
}
}
// 使用示例
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evens = CollectionUtils.filter(numbers, n -> n % 2 == 0);
4. 受限泛型(边界类型参数)
通过extends和super关键字限制类型参数的范围。
public class NumberProcessor {
// 上界通配符
public static double sum(List<? extends Number> numbers) {
return numbers.stream()
.mapToDouble(Number::doubleValue)
.sum();
}
// 下界通配符
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 5; i++) {
list.add(i);
}
}
}
// 使用示例
List<Integer> integers = new ArrayList<>();
List<Number> numbers = new ArrayList<>();
NumberProcessor.addNumbers(integers); // OK
NumberProcessor.addNumbers(numbers); // OK
double sum = NumberProcessor.sum(integers); // OK
5. 类型推断与菱形语法
JDK1.8增强了类型推断能力,结合lambda表达式使用更加简洁。
// 类型推断示例
public class TypeInference {
public static <T> T getDefaultValue(Supplier<T> supplier) {
return supplier.get();
}
}
// 使用示例
String defaultValue = TypeInference.getDefaultValue(() -> "default"); // 自动推断T为String
// 菱形语法
List<String> names = new ArrayList<>(); // JDK1.7+支持
Map<String, List<Integer>> map = new HashMap<>(); // 嵌套泛型
三、项目中泛型的典型应用场景
1. 集合框架(java.util包)
// 典型集合使用
List<String> stringList = new ArrayList<>();
Map<Integer, String> idToNameMap = new HashMap<>();
Set<LocalDate> holidaySet = new HashSet<>();
// Stream API中的泛型
List<User> users = /* ... */;
List<String> names = users.stream()
.map(User::getName) // 方法引用
.collect(Collectors.toList());
2. 函数式接口(java.util.function包)
// Function接口的泛型定义
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
return (V v) -> apply(before.apply(v));
}
}
// 使用示例
Function<String, Integer> parseInt = Integer::parseInt;
Function<Integer, String> toHexString = Integer::toHexString;
Function<String, String> parseAndHex = toHexString.compose(parseInt);
String hex = parseAndHex.apply("255"); // "ff"
3. Optional类(避免空指针)
public Optional<User> findUserById(Long id) {
// 模拟数据库查询
return id > 0 ? Optional.of(new User(id, "User" + id)) : Optional.empty();
}
// 使用示例
Optional<User> userOpt = findUserById(1L);
String name = userOpt.map(User::getName)
.orElse("Default");
4. 自定义业务封装
// 分页结果泛型封装
public class PageResult<T> {
private int pageNum;
private int pageSize;
private long total;
private List<T> data;
// 构造器、getter/setter省略
// 泛型静态工厂方法
public static <T> PageResult<T> of(List<T> data, int pageNum, int pageSize, long total) {
PageResult<T> result = new PageResult<>();
result.setData(data);
result.setPageNum(pageNum);
result.setPageSize(pageSize);
result.setTotal(total);
return result;
}
}
// 使用示例
List<Product> products = productService.queryProducts();
PageResult<Product> page = PageResult.of(products, 1, 10, 100);
5. 反射API中的泛型
// 获取泛型实际类型
public class GenericType<T> {
private final Class<T> type;
@SuppressWarnings("unchecked")
public GenericType() {
this.type = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public Class<T> getType() {
return type;
}
}
// 使用示例
GenericType<String> stringType = new GenericType<String>() {};
System.out.println(stringType.getType()); // 输出class java.lang.String
四、JDK1.8泛型新特性与最佳实践
1. 目标类型推断增强
// JDK1.8之前需要显式指定类型
List<String> list = Collections.<String>emptyList();
// JDK1.8可以自动推断
List<String> list = Collections.emptyList();
2. 与Lambda表达式结合
// 泛型与Lambda完美结合
public static <T> void processList(List<T> list, Consumer<T> processor) {
list.forEach(processor);
}
// 使用示例
List<String> names = Arrays.asList("Alice", "Bob");
processList(names, name -> System.out.println("Hello, " + name));
3. 方法引用中的泛型
// 泛型方法引用
public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
return list.stream().map(mapper).collect(Collectors.toList());
}
// 使用示例
List<String> numbers = Arrays.asList("1", "2", "3");
List<Integer> ints = map(numbers, Integer::parseInt);
4. 最佳实践建议
- 优先使用泛型方法:当只有部分方法需要泛型时,不要将整个类泛型化
- 合理使用通配符:PECS原则(Producer Extends, Consumer Super)
- 避免原生类型:如使用
List而非List<String> - 类型安全优先:必要时使用
@SuppressWarnings("unchecked")但要添加说明 - 文档化泛型参数:使用Javadoc说明类型参数的约束条件
五、总结
JDK1.8中的泛型机制已经非常成熟,它深度集成在Java集合框架、函数式编程和类型系统中。合理使用泛型可以:
- 大幅提高代码的类型安全性
- 增强API的灵活性和表现力
- 减少重复代码和样板代码
- 与Stream API、Lambda表达式协同工作,构建更优雅的代码

1137

被折叠的 条评论
为什么被折叠?



