本文目录导读:

Java泛型编程实战案例
泛型是Java中非常重要的特性,它允许在编译时进行类型检查,提高代码的复用性和安全性,下面通过几个典型案例来展示泛型的实际应用。
泛型类 - 通用容器实现
// 泛型类定义
public class GenericBox<T> {
private T content;
public GenericBox(T content) {
this.content = content;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
public boolean isEmpty() {
return content == null;
}
@Override
public String toString() {
return "Box contains: " + content;
}
// 使用示例
public static void main(String[] args) {
// 存储字符串
GenericBox<String> stringBox = new GenericBox<>("Hello");
System.out.println(stringBox);
// 存储整数(自动装箱)
GenericBox<Integer> integerBox = new GenericBox<>(42);
System.out.println(integerBox);
// 存储自定义对象
GenericBox<List<String>> listBox = new GenericBox<>(Arrays.asList("A", "B"));
System.out.println(listBox);
}
}
泛型方法 - 通用排序算法
public class GenericSort {
// 泛型方法:对任意类型数组进行排序
public static <T extends Comparable<T>> void sort(T[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i].compareTo(array[j]) > 0) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
// 泛型方法:打印数组
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
// 使用示例
public static void main(String[] args) {
// 排序整数数组
Integer[] intArray = {3, 1, 4, 1, 5, 9};
System.out.println("排序前:");
printArray(intArray);
sort(intArray);
System.out.println("排序后:");
printArray(intArray);
// 排序字符串数组
String[] strArray = {"banana", "apple", "cherry", "date"};
System.out.println("\n排序前:");
printArray(strArray);
sort(strArray);
System.out.println("排序后:");
printArray(strArray);
}
}
泛型接口 - 数据仓库模式
// 泛型接口
public interface Repository<T, ID> {
T findById(ID id);
List<T> findAll();
void save(T entity);
void delete(T entity);
void deleteById(ID id);
}
// 实现泛型接口 - 用户仓库
public class UserRepository implements Repository<User, Long> {
private Map<Long, User> userDatabase = new HashMap<>();
private static long idCounter = 1;
@Override
public User findById(Long id) {
return userDatabase.get(id);
}
@Override
public List<User> findAll() {
return new ArrayList<>(userDatabase.values());
}
@Override
public void save(User entity) {
if (entity.getId() == null) {
entity.setId(idCounter++);
}
userDatabase.put(entity.getId(), entity);
}
@Override
public void delete(User entity) {
userDatabase.remove(entity.getId());
}
@Override
public void deleteById(Long id) {
userDatabase.remove(id);
}
}
// 用户实体类
public class User {
private Long id;
private String name;
private String email;
// 构造器、getter/setter省略
public User(String name, String email) {
this.name = name;
this.email = email;
}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', email='" + email + "'}";
}
// 使用示例
public static void main(String[] args) {
UserRepository userRepo = new UserRepository();
// 创建用户
User user1 = new User("张三", "zhangsan@example.com");
User user2 = new User("李四", "lisi@example.com");
// 保存用户
userRepo.save(user1);
userRepo.save(user2);
// 查询所有用户
System.out.println("所有用户:");
userRepo.findAll().forEach(System.out::println);
// 根据ID查询
System.out.println("\n查找ID为1的用户:" + userRepo.findById(1L));
}
}
通配符 - 灵活的数据处理
public class WildcardDemo {
// 使用通配符处理不同类型的集合
public static void processNumbers(List<? extends Number> numbers) {
double sum = 0;
for (Number num : numbers) {
sum += num.doubleValue();
}
System.out.println("Sum: " + sum);
}
// 上界通配符 - 只能读取,不能写入
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
// 下界通配符 - 可以写入特定类型
public static void addIntegers(List<? super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
public static void main(String[] args) {
// 上界通配符示例
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
processNumbers(intList); // 可以处理Integer列表
processNumbers(doubleList); // 也可以处理Double列表
// 下界通配符示例
List<Number> numberList = new ArrayList<>();
addIntegers(numberList); // 可以向Number列表添加Integer
System.out.println("Number列表内容:");
printList(numberList);
}
}
类型擦除与桥接方法
// 演示类型擦除机制
public class TypeErasureDemo<T> {
private T value;
public TypeErasureDemo(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
// 编译后的等价代码(类型擦除后)
// public class TypeErasureDemo {
// private Object value;
//
// public TypeErasureDemo(Object value) {
// this.value = value;
// }
//
// public Object getValue() {
// return value;
// }
//
// public void setValue(Object value) {
// this.value = value;
// }
// }
public static void main(String[] args) {
// 运行时类型检查
TypeErasureDemo<String> demo1 = new TypeErasureDemo<>("Hello");
TypeErasureDemo<Integer> demo2 = new TypeErasureDemo<>(42);
// 无法在运行时区分具体类型
System.out.println(demo1.getClass() == demo2.getClass()); // 输出: true
// 使用反射验证类型擦除
try {
java.lang.reflect.Field field = TypeErasureDemo.class.getDeclaredField("value");
System.out.println("字段类型: " + field.getType().getName()); // 输出: java.lang.Object
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
高级应用 - 泛型工厂模式
// 泛型工厂接口
public interface GenericFactory<T> {
T create();
T create(Object... args);
}
// 具体实现
public class UserFactory implements GenericFactory<User> {
@Override
public User create() {
return new User("默认用户", "default@example.com");
}
@Override
public User create(Object... args) {
if (args.length >= 2 && args[0] instanceof String && args[1] instanceof String) {
return new User((String) args[0], (String) args[1]);
}
return create(); // 默认创建
}
public static void main(String[] args) {
GenericFactory<User> userFactory = new UserFactory();
// 创建默认用户
User defaultUser = userFactory.create();
System.out.println("默认用户: " + defaultUser);
// 创建自定义用户
User customUser = userFactory.create("王五", "wangwu@example.com");
System.out.println("自定义用户: " + customUser);
}
}
泛型使用最佳实践
- 优先使用泛型:尽量使用泛型而不是Object类型
- 限制类型范围:使用有界类型参数(如
<T extends Comparable<T>>) - PECS原则:Producer Extends, Consumer Super
- 避免混合使用:不要在同一方法中混用原始类型和泛型
- 注意类型擦除:理解泛型在运行时的限制
- 使用@SuppressWarnings注解:仅在必要时抑制未检查警告
这些案例展示了泛型在实际开发中的多种应用场景,帮助你更好地理解和运用泛型编程。