前言 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 = 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); 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<String> stringList = new ArrayList <>(); stringList.add("字符串" ); 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 ); 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 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 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); } @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); } 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 () { String[] names = {"Alice" , "Bob" , "Charlie" }; System.out.println("交换前: " + Arrays.toString(names)); swap(names, 0 , 2 ); System.out.println("交换后: " + Arrays.toString(names)); Integer[] numbers = {1 , 2 , 3 , 4 , 5 }; int index = indexOf(numbers, 3 ); System.out.println("数字3的索引: " + index); List<String> filledList = createFilledList("Hello" , 3 ); System.out.println("填充列表: " + filledList); Object obj = "这是一个字符串" ; String str = safeCast(obj, String.class); System.out.println("安全转换: " + str); String[] keys = {"name" , "age" , "city" }; Object[] values = {"张三" , 25 , "北京" }; Map<String, Object> map = createMap(keys, values); System.out.println("创建的映射: " + map); 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); } } 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 { 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); } } 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 <>(); addElements(objectList, "字符串" , 123 , 3.14 , true ); System.out.println("Object列表: " + objectList); addElements(numberList, 1 , 2.5 , 3.14f ); System.out.println("Number列表: " + numberList); 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); 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 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<?>) { System.out.println("stringList是List的实例" ); } } public void demonstrateGenericArrayLimitations () { 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)); 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 { public class GenericClass <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; @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 <U> U staticMethod (U param) { return param; } static class StaticInnerClass { } } 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); } 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 ); 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 ); 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 ); String expiredValue = stringCache.get("user:1" ); System.out.println("过期后的值: " + expiredValue); } 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; } 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泛型是一个强大而重要的特性,它提供了类型安全、代码重用和性能优化等诸多优势。通过本文的学习,我们深入了解了:
泛型基础 :理解了泛型的概念、优势和基本语法
泛型类与接口 :掌握了如何定义和使用泛型类和接口
泛型方法 :学会了定义灵活的泛型方法
通配符机制 :理解了上界、下界和无界通配符的使用场景
类型擦除 :了解了Java泛型的实现机制和相关限制
实际应用 :通过实例展示了泛型在实际开发中的应用
掌握Java泛型对于编写类型安全、可维护的代码至关重要。在实际开发中,合理使用泛型不仅能提高代码质量,还能提升开发效率。建议开发者:
优先使用泛型集合而不是原始类型
合理设计泛型API以提高代码重用性
理解通配符的使用场景,避免类型转换错误
注意泛型的限制,选择合适的设计方案
在团队开发中制定一致的泛型使用规范
通过不断实践和应用,您将能够更加熟练地使用Java泛型,编写出更加优雅和健壮的代码。
参考资料