App 2 months ago
parent
commit
1df6ae6ea8
  1. 100
      w8/AI.txt
  2. 155
      w8/Cache.java
  3. 27
      w8/CacheTest.java
  4. 67
      w8/Pair.java
  5. 20
      w8/PairTest.java
  6. BIN
      w8/QQ20260430-092036.png
  7. BIN
      w8/QQ20260430-092544.png

100
w8/AI.txt

@ -0,0 +1,100 @@
问题:Java泛型擦除后如何通过反射获取泛型信息?
答:虽然 Java 在编译时会进行类型擦除(Type Erasure),将泛型替换为原始类型(通常是 Object 或边界类型),但某些情况下泛型信息会被保留在字节码中,可以通过反射获取:
1. 获取父类/接口的泛型参数
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
// 继承泛型类时指定具体类型
public class StringList extends ArrayList<String> {}
public class GenericReflectionDemo {
public static void main(String[] args) {
// 获取父类的泛型参数
Class<?> clazz = StringList.class;
Type genericSuperclass = clazz.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericSuperclass;
Type[] actualTypeArgs = pt.getActualTypeArguments();
for (Type type : actualTypeArgs) {
System.out.println("泛型参数类型: " + type);
// 输出: class java.lang.String
}
}
}
}
2. 获取字段的泛型类型
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class GenericField {
private List<String> names;
private Map<Integer, String> mapping;
}
// 获取字段泛型
Field field = GenericField.class.getDeclaredField("names");
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) genericType;
System.out.println("字段泛型参数: " +
Arrays.toString(pt.getActualTypeArguments()));
// 输出: [class java.lang.String]
}
3. 获取方法参数的泛型类型
Java
1
2
3
4
public void process(List<String> items, Map<K, V> map) {}
Method method = clazz.getMethod("process", List.class, Map.class);
Type[] paramTypes = method.getGenericParameterTypes();
4. 核心 API 总结
反射方法 用途
getGenericSuperclass() 获取父类的泛型类型
getGenericInterfaces() 获取接口的泛型类型
Field.getGenericType() 获取字段的泛型类型
Method.getGenericReturnType() 获取返回值的泛型类型
Method.getGenericParameterTypes() 获取方法参数的泛型类型
ParameterizedType.getActualTypeArguments() 获取实际泛型参数
⚠️ 限制:局部变量和方法参数的泛型信息在运行时是完全擦除的,无法通过反射获取。

155
w8/Cache.java

@ -0,0 +1,155 @@
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Collection;
import java.util.Optional;
import java.util.HashSet;
import java.util.ArrayList;
/**
* 泛型缓存类 Cache<K, V>
* 提供简单的键值缓存机制非线程安全
* @param <K> 键的类型
* @param <V> 值的类型
*/
public class Cache<K, V> {
private final Map<K, V> cache;
private final int maxSize;
// 统计信息
private long hitCount = 0;
private long missCount = 0;
/**
* 默认构造方法 - 无容量限制
*/
public Cache() {
this(Integer.MAX_VALUE);
}
/**
* 带容量限制的构造方法
*/
public Cache(int maxSize) {
this.maxSize = maxSize;
this.cache = new HashMap<>();
}
/**
* 存入缓存
*/
public void put(K key, V value) {
if (key == null) {
throw new IllegalArgumentException("Key cannot be null");
}
if (cache.size() >= maxSize && !cache.containsKey(key)) {
throw new IllegalStateException("Cache is full, no eviction strategy implemented");
}
cache.put(key, value);
}
/**
* 从缓存获取
*/
public V get(K key) {
if (cache.containsKey(key)) {
hitCount++;
return cache.get(key);
} else {
missCount++;
return null;
}
}
/**
* 使用 Optional 包装返回值更安全的API
*/
public Optional<V> getOptional(K key) {
return Optional.ofNullable(get(key));
}
/**
* 判断缓存中是否存在键
*/
public boolean containsKey(K key) {
return cache.containsKey(key);
}
/**
* 从缓存中移除
*/
public V remove(K key) {
return cache.remove(key);
}
/**
* 清空缓存
*/
public void clear() {
cache.clear();
hitCount = 0;
missCount = 0;
}
/**
* 获取缓存大小
*/
public int size() {
return cache.size();
}
/**
* 判断缓存是否为空
*/
public boolean isEmpty() {
return cache.isEmpty();
}
/**
* 获取所有键
*/
public Set<K> keySet() {
return new HashSet<>(cache.keySet());
}
/**
* 获取所有值
*/
public Collection<V> values() {
return new ArrayList<>(cache.values());
}
/**
* 获取命中率
*/
public double getHitRate() {
long total = hitCount + missCount;
return total == 0 ? 0.0 : (double) hitCount / total;
}
/**
* 获取统计信息
*/
public CacheStats getStats() {
return new CacheStats(hitCount, missCount, getHitRate());
}
// 统计信息内部类
public static class CacheStats {
public final long hits;
public final long misses;
public final double hitRate;
public CacheStats(long hits, long misses, double hitRate) {
this.hits = hits;
this.misses = misses;
this.hitRate = hitRate;
}
@Override
public String toString() {
return String.format("CacheStats{hits=%d, misses=%d, hitRate=%.2f%%}",
hits, misses, hitRate * 100);
}
}
}

27
w8/CacheTest.java

@ -0,0 +1,27 @@
public class CacheTest {
public static void main(String[] args) {
// 创建缓存实例
Cache<String, Integer> ageCache = new Cache<>(100);
// 存入数据
ageCache.put("Alice", 25);
ageCache.put("Bob", 30);
ageCache.put("Charlie", 35);
// 获取数据
System.out.println("Alice's age: " + ageCache.get("Alice"));
// 测试缓存未命中
Integer davidAge = ageCache.get("David");
System.out.println("David's age: " + davidAge);
// 查看统计信息
System.out.println(ageCache.getStats());
// 使用 Optional API
ageCache.getOptional("Eve").ifPresentOrElse(
age -> System.out.println("Found: " + age),
() -> System.out.println("Eve not found")
);
}
}

67
w8/Pair.java

@ -0,0 +1,67 @@
/**
* 泛型 Pair - 用于存储键值对
* @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;
}
// Getter 方法
public K getKey() {
return key;
}
public V getValue() {
return value;
}
// Setter 方法
public void setKey(K key) {
this.key = key;
}
public void setValue(V value) {
this.value = value;
}
/**
* swap 方法 - 交换当前 Pair key value
* 注意只有当 K V 类型相同时才能交换否则返回新 Pair
*/
public Pair<V, K> swap() {
return new Pair<>(value, key);
}
/**
* 静态泛型方法 - 交换任意两个 Pair 对象
*/
public static <K, V> Pair<V, K> swap(Pair<K, V> pair) {
return new Pair<>(pair.getValue(), pair.getKey());
}
@Override
public String toString() {
return "Pair{" + "key=" + key + ", value=" + value + '}';
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) obj;
return java.util.Objects.equals(key, pair.key) &&
java.util.Objects.equals(value, pair.value);
}
@Override
public int hashCode() {
return java.util.Objects.hash(key, value);
}
}

20
w8/PairTest.java

@ -0,0 +1,20 @@
public class PairTest {
public static void main(String[] args) {
// 测试整数-字符串 Pair
Pair<Integer, String> pair1 = new Pair<>(1, "One");
System.out.println("原 Pair: " + pair1);
// 使用实例方法 swap
Pair<String, Integer> swapped = pair1.swap();
System.out.println("交换后: " + swapped);
// 使用静态方法 swap
Pair<String, Integer> swapped2 = Pair.swap(pair1);
System.out.println("静态交换: " + swapped2);
// 测试相同类型的 Pair 交换
Pair<String, String> pair2 = new Pair<>("A", "B");
Pair<String, String> swappedSame = pair2.swap();
System.out.println("同类型交换: " + swappedSame);
}
}

BIN
w8/QQ20260430-092036.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
w8/QQ20260430-092544.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Loading…
Cancel
Save