From 8958a9367e0e29f95d5957a32975fa5df38a2eec Mon Sep 17 00:00:00 2001 From: ZhengShiyi <1980003269@qq.com> Date: Tue, 28 Apr 2026 17:08:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4Java=E6=B3=9B=E5=9E=8B?= =?UTF-8?q?=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- W8/Cache.java | 64 ++++++ ...Žå¦‚何通过åå°„èŽ·å–æ³›åž‹ä¿¡æ¯.txt | 84 ++++++++ W8/Pair.java | 47 +++++ W8/代ç å®¡æŸ¥æŠ¥å‘Š.md | 190 ++++++++++++++++++ 4 files changed, 385 insertions(+) create mode 100644 W8/Cache.java create mode 100644 W8/Java泛型擦除åŽå¦‚何通过åå°„èŽ·å–æ³›åž‹ä¿¡æ¯.txt create mode 100644 W8/Pair.java create mode 100644 W8/代ç å®¡æŸ¥æŠ¥å‘Š.md diff --git a/W8/Cache.java b/W8/Cache.java new file mode 100644 index 0000000..ca21d13 --- /dev/null +++ b/W8/Cache.java @@ -0,0 +1,64 @@ +import java.util.HashMap; +import java.util.Map; + +public class Cache { + // 底层用 HashMap å­˜å‚¨æ•°æ® + private final Map cacheMap; + + public Cache() { + this.cacheMap = new HashMap<>(); + } + + // 存入缓存 + public void put(K key, V value) { + cacheMap.put(key, value); + } + + // ä»Žç¼“å­˜èŽ·å– + public V get(K key) { + return cacheMap.get(key); + } + + // 删除缓存 + public void remove(K key) { + cacheMap.remove(key); + } + + // 判断缓存是å¦åŒ…嫿Ÿä¸ª key + public boolean containsKey(K key) { + return cacheMap.containsKey(key); + } + + // 清空缓存 + public void clear() { + cacheMap.clear(); + } + + // 获å–ç¼“å­˜å¤§å° + public int size() { + return cacheMap.size(); + } + + // 测试主方法 + public static void main(String[] args) { + Cache studentScoreCache = new Cache<>(); + + // å­˜å…¥æ•°æ® + studentScoreCache.put("张三", 90); + studentScoreCache.put("æŽå››", 85); + studentScoreCache.put("王五", 95); + + // æŸ¥è¯¢æ•°æ® + System.out.println("张三的分数:" + studentScoreCache.get("张三")); + System.out.println("缓存大å°ï¼š" + studentScoreCache.size()); + + // åˆ é™¤æ•°æ® + studentScoreCache.remove("æŽå››"); + System.out.println("删除æŽå››åŽç¼“存大å°ï¼š" + studentScoreCache.size()); + System.out.println("是å¦åŒ…嫿Žå››ï¼Ÿ" + studentScoreCache.containsKey("æŽå››")); + + // 清空缓存 + studentScoreCache.clear(); + System.out.println("清空åŽç¼“存大å°ï¼š" + studentScoreCache.size()); + } +} \ No newline at end of file diff --git a/W8/Java泛型擦除åŽå¦‚何通过åå°„èŽ·å–æ³›åž‹ä¿¡æ¯.txt b/W8/Java泛型擦除åŽå¦‚何通过åå°„èŽ·å–æ³›åž‹ä¿¡æ¯.txt new file mode 100644 index 0000000..8159e3b --- /dev/null +++ b/W8/Java泛型擦除åŽå¦‚何通过åå°„èŽ·å–æ³›åž‹ä¿¡æ¯.txt @@ -0,0 +1,84 @@ + 一ã€Java 泛型擦除的本质 +Java 的泛型是一ç§ç¼–译期语法糖,并éžåŽŸç”Ÿæ”¯æŒçš„语言特性。为了兼容 JDK 1.5 之剿²¡æœ‰æ³›åž‹çš„代ç ï¼Œç¼–译器会在编译阶段执行类型擦除(Type Erasure): + +1. æ“¦é™¤æ³›åž‹å‚æ•° + æ‰€æœ‰æ³›åž‹ç±»åž‹å‚æ•°ï¼ˆå¦‚ ``ã€``)会被替æ¢ä¸ºå®ƒä»¬çš„上界类型: + - 未指定上界时,默认擦除为 `Object`。 + 例如 `List` → 编译åŽå˜ä¸º `List`,`add` æ–¹æ³•å˜æˆ `add(Object)`,`get` 方法返回 `Object`。 + - 指定上界时,擦除为上界类型。 + 例如 `List` → ç¼–è¯‘åŽæ“¦é™¤ä¸º `List`。 + +2. æ’å…¥å¼ºåˆ¶ç±»åž‹è½¬æ¢ + 为了ä¿è¯ä»£ç åœ¨è¿è¡Œæ—¶çš„ç±»åž‹å®‰å…¨ï¼Œç¼–è¯‘å™¨ä¼šåœ¨è¯»å–æ³›åž‹å…ƒç´ çš„地方自动æ’入强制类型转æ¢ã€‚ + 例如 `String s = list.get(0);` 编译åŽä¼šå˜æˆ `String s = (String) list.get(0);`。 + +核心结果: +è¿è¡Œæ—¶ JVM åªèƒ½çœ‹åˆ°åŽŸå§‹ç±»åž‹ï¼ˆå¦‚ `List`ã€`Map`),无法直接感知到 `String`ã€`Integer` è¿™ç±»æ³›åž‹å‚æ•°ä¿¡æ¯ã€‚ + + 二ã€ä¸ºä»€ä¹ˆè¿˜èƒ½é€šè¿‡å射获å–部分泛型信æ¯ï¼Ÿ +虽然大部分泛型信æ¯è¢«æ“¦é™¤äº†ï¼Œä½†æœ‰ä¸€éƒ¨åˆ†ç»“构级别的泛型信æ¯ä¼šè¢«ç¼–译器刻æ„ä¿ç•™ï¼Œå¹¶å†™å…¥ `.class` å­—èŠ‚ç æ–‡ä»¶çš„ `Signature` 属性中。 + +1. 哪些泛型信æ¯ä¼šè¢«ä¿ç•™ï¼Ÿ +åªæœ‰å®šä¹‰åœ¨ç±»ã€æŽ¥å£ã€æˆå‘˜å˜é‡ã€æ–¹æ³•ç­¾å上的泛型信æ¯ä¼šè¢«ä¿ç•™ï¼Œå…·ä½“包括: +- ç±»/接å£çš„父类/实现接å£å£°æ˜Ž + 例如 `public class MyList extends ArrayList`,`ArrayList` 这个带泛型的父类信æ¯ä¼šè¢«ä¿ç•™ã€‚ +- 类中æˆå‘˜å˜é‡ï¼ˆField)的泛型类型 + 例如 `private List scores;`,`List` 的泛型信æ¯ä¼šè¢«ä¿ç•™ã€‚ +- 方法(Methodï¼‰çš„å‚æ•°ç±»åž‹ä¸Žè¿”回值类型 + 例如 `public List getNames(List ids)`ï¼Œå‚æ•°å’Œè¿”回值的泛型信æ¯ä¼šè¢«ä¿ç•™ã€‚ + + 2. 为什么这些信æ¯ä¼šè¢«ä¿ç•™ï¼Ÿ +- 为了ä¿è¯ç¼–译器的类型检查:IDE 和编译器需è¦è¿™äº›ä¿¡æ¯æ¥æ£€æŸ¥ä»£ç çš„类型安全。 +- 为了支æŒåå°„ API:JDK 设计了专门的åå°„æŽ¥å£æ¥è¯»å–这些信æ¯ï¼Œä¿è¯æ¡†æž¶ï¼ˆå¦‚ Springã€Jackson)能基于泛型åšè‡ªåŠ¨åŒ–å¤„ç†ã€‚ +- 这些信æ¯ä¿å­˜åœ¨å­—节ç çš„ `Signature` 属性中,ä¸ä¼šå½±å“è¿è¡Œæ—¶çš„兼容性。 + + 三ã€é€šè¿‡åå°„èŽ·å–æ³›åž‹ä¿¡æ¯çš„æ­¥éª¤ + + 步骤 1:获å–目标的å射元数æ®å¯¹è±¡ +æ ¹æ®ä½ è¦èŽ·å–的泛型类型,先拿到对应的元数æ®å¯¹è±¡ï¼š +- 获å–ç±»/父类的泛型:拿到目标类的 `Class` 对象。 +- èŽ·å–æˆå‘˜å˜é‡çš„æ³›åž‹ï¼šæ‹¿åˆ°ç›®æ ‡å˜é‡çš„ `Field` 对象。 +- èŽ·å–æ–¹æ³•傿•°/返回值的泛型:拿到目标方法的 `Method` 对象。 + + 步骤 2:调用 `getGenericXXX()` 方法获å–带泛型的 `Type` 对象 +åå°„ API æä¾›äº†ä¸“门的方法,æ¥è¯»å–字节ç ä¸­ä¿ç•™çš„ `Signature` ä¿¡æ¯ï¼Œè¿”回一个 `java.lang.reflect.Type` 对象(它是所有类型的通用接å£ï¼‰ï¼š +- 父类:`Class.getGenericSuperclass()` +- 实现接å£ï¼š`Class.getGenericInterfaces()` +- æˆå‘˜å˜é‡ç±»åž‹ï¼š`Field.getGenericType()` +- 方法返回值类型:`Method.getGenericReturnType()` +- æ–¹æ³•å‚æ•°ç±»åž‹ï¼š`Method.getGenericParameterTypes()` + +注æ„:这些方法和普通的 `getSuperclass()`ã€`getType()` ä¸åŒï¼ŒåŽè€…返回的是擦除åŽçš„原始类型(如 `ArrayList`),而å‰è€…返回的是ä¿ç•™äº†æ³›åž‹ä¿¡æ¯çš„ `Type` 对象。 + +步骤 3ï¼šåˆ¤æ–­å¹¶è§£æž `ParameterizedType`ï¼ˆå‚æ•°åŒ–类型) +`Type` 是一个空接å£ï¼Œå®ƒçš„一个é‡è¦å®žçŽ°æ˜¯ `ParameterizedType`,用æ¥è¡¨ç¤ºå¸¦æ³›åž‹çš„傿•°åŒ–类型(如 `List`ã€`Map`)。 + +你需è¦å…ˆåˆ¤æ–­èŽ·å–到的 `Type` æ˜¯å¦æ˜¯ `ParameterizedType` 实例: +- 如果是,就å¯ä»¥è°ƒç”¨å®ƒçš„æ ¸å¿ƒæ–¹æ³• `getActualTypeArguments()`,这个方法会返回一个 `Type[]` 数组,里é¢å°±æ˜¯å®šä¹‰æ—¶å£°æ˜Žçš„çœŸå®žæ³›åž‹å‚æ•°ã€‚ +- 数组里的æ¯ä¸ªå…ƒç´ ï¼Œéƒ½å¯¹åº”ç€åŽŸå§‹å£°æ˜Žä¸­çš„æ³›åž‹å‚æ•°ï¼ˆå¦‚ `List` 会返回一个长度为 1 的数组,元素为 `String`ï¼›`Map` 会返回长度为 2 的数组,分别为 `K` å’Œ `V`)。 + +步骤 4:递归解æžåµŒå¥—泛型(如 `List>`) +å¦‚æžœæ³›åž‹æœ¬èº«è¿˜æ˜¯ä¸€ä¸ªå‚æ•°åŒ–类型(如 `List>`),`getActualTypeArguments()` 返回的 `Type` ä»ç„¶æ˜¯ä¸€ä¸ª `ParameterizedType`,你å¯ä»¥é‡å¤æ­¥éª¤ 3,递归解æžåµŒå¥—的泛型信æ¯ã€‚ + + å››ã€ä¸åŒåœºæ™¯ä¸‹çš„获å–能力对比 +| 场景 | 示例 | 能å¦é€šè¿‡åå°„èŽ·å–æ³›åž‹ä¿¡æ¯ï¼Ÿ | 原因 | + +| 类继承的父类泛型 | `class A extends B` | ✅ 能 | ä¿¡æ¯ä¿å­˜åœ¨ç±»çš„ `Signature` 属性中 | +| ç±»å®žçŽ°çš„æŽ¥å£æ³›åž‹ | `class C implements D` | ✅ 能 | ä¿¡æ¯ä¿å­˜åœ¨ç±»çš„ `Signature` 属性中 | +| æˆå‘˜å˜é‡çš„æ³›åž‹ | `private List list;` | ✅ 能 | ä¿¡æ¯ä¿å­˜åœ¨å­—段的 `Signature` 属性中 | +| 方法返回值的泛型 | `public List getList()` | ✅ 能 | ä¿¡æ¯ä¿å­˜åœ¨æ–¹æ³•çš„ `Signature` 属性中 | +| æ–¹æ³•å‚æ•°çš„æ³›åž‹ | `public void setList(List list)` | ✅ 能 | ä¿¡æ¯ä¿å­˜åœ¨æ–¹æ³•çš„ `Signature` 属性中 | +| 方法内局部å˜é‡çš„æ³›åž‹ | `public void test() { List l = new ArrayList<>(); }` | ⌠ä¸èƒ½ | 局部å˜é‡çš„æ³›åž‹ä¿¡æ¯ç¼–译åŽå®Œå…¨æ“¦é™¤ï¼Œæ— ä»»ä½•ä¿ç•™ | +| 直接创建的泛型对象 | `new ArrayList()` | ⌠ä¸èƒ½ | 仅在编译期有效,è¿è¡Œæ—¶æ²¡æœ‰ä»»ä½•å…ƒæ•°æ® | + +五ã€å±€é™æ€§ä¸Žæ³¨æ„事项 +1. åªèƒ½èŽ·å–定义时声明的泛型,无法获å–è¿è¡Œæ—¶ä¼ å…¥çš„类型 + 例如 `List list = new ArrayList<>();`,åå°„æ— æ³•çŸ¥é“ `list` 里存的是 `String`,åªèƒ½çŸ¥é“ `list` 这个å˜é‡å£°æ˜Žæ—¶çš„类型是 `List`。 +2. 无法获å–通é…符泛型的具体类型 + 例如 `List`,å射能知é“它的上界是 `Number`,但无法知é“è¿è¡Œæ—¶å®žé™…传入的具体å­ç±»åž‹ã€‚ +3. 类型å˜é‡ï¼ˆå¦‚ ``)的解æžéœ€è¦ä¸Šä¸‹æ–‡ + 如果是未绑定的类型å˜é‡ï¼ˆå¦‚ `class Box` 中的 `T`),åå°„åªèƒ½èŽ·å–到å˜é‡å,无法知é“它的具体类型,除éžå®ƒè¢«ç»‘定到了具体的类上(如 `class StringBox extends Box`)。 + + + å…­ã€æ€»ç»“ +Java 泛型擦除åŽï¼Œè¿è¡Œæ—¶å¤§éƒ¨åˆ†æ³›åž‹ä¿¡æ¯ä¼šè¢«ç§»é™¤ï¼Œä½†ç±»ã€æŽ¥å£ã€æˆå‘˜å˜é‡ã€æ–¹æ³•ç­¾å上声明的泛型信æ¯ä¼šè¢«ä¿ç•™åœ¨å­—节ç çš„ `Signature` 属性中。通过åå°„ API 获å–这些元数æ®ï¼Œå°†å…¶è§£æžä¸º `ParameterizedType` 并调用 `getActualTypeArguments()`,å³å¯è¯»å–对应的泛型信æ¯ï¼›è€Œæ–¹æ³•内局部å˜é‡çš„æ³›åž‹ä¿¡æ¯ä¼šè¢«å®Œå…¨æ“¦é™¤ï¼Œæ— æ³•通过å射获å–。 diff --git a/W8/Pair.java b/W8/Pair.java new file mode 100644 index 0000000..68a30ae --- /dev/null +++ b/W8/Pair.java @@ -0,0 +1,47 @@ +public class Pair { + 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; + } + + // swap æ–¹æ³•ï¼šäº¤æ¢ key å’Œ value + public Pair swap() { + return new Pair<>(this.value, this.key); + } + + @Override + public String toString() { + return "Pair{" + + "key=" + key + + ", value=" + value + + '}'; + } + + // 测试主方法 + public static void main(String[] args) { + Pair pair = new Pair<>("年龄", 20); + System.out.println("原对象:" + pair); + + Pair swapped = pair.swap(); + System.out.println("交æ¢åŽï¼š" + swapped); + } +} \ No newline at end of file diff --git a/W8/代ç å®¡æŸ¥æŠ¥å‘Š.md b/W8/代ç å®¡æŸ¥æŠ¥å‘Š.md new file mode 100644 index 0000000..9a37f07 --- /dev/null +++ b/W8/代ç å®¡æŸ¥æŠ¥å‘Š.md @@ -0,0 +1,190 @@ +# 代ç å®¡æŸ¥æŠ¥å‘Šï¼ˆCache 泛型缓存类) + +### 一ã€ä»£ç æ•´ä½“评价 + +è¿™æ®µä»£ç æ•´ä½“è´¨é‡å¾ˆé«˜ï¼Œå®žçŽ°äº†ä¸€ä¸ªåŸºäºŽæ³›åž‹çš„é”®å€¼ç¼“å­˜ï¼ŒåŠŸèƒ½å®Œæ•´ã€ç»“构清晰ã€ç¬¦åˆ Java ç¼–ç è§„èŒƒï¼Œå®Œå…¨æ»¡è¶³ä½œä¸šè¦æ±‚。 + +#### 二ã€ä»£ç ä¼˜ç‚¹ + +正确使用泛型 泛型定义规范,支æŒä»»æ„类型的键值对,通用性强。 + +å°è£…性良好使用 private final Map 存储数æ®ï¼Œå¤–部无法直接修改,ä¿è¯æ•°æ®å®‰å…¨ã€‚ + +功能完整实现了缓存的核心æ“作: + +添加 put + +èŽ·å– get + +删除 remove + +判断存在 containsKey + +清空 clear + +获å–å¤§å° size + +代ç ç®€æ´æ˜“读方法命åè§„èŒƒã€æ³¨é‡Šæ¸…æ™°ã€é€»è¾‘ç›´ç™½ï¼Œç¬¦åˆ Java 标准写法。 + +自带测试方法main 方法æä¾›å®Œæ•´æµ‹è¯•用例,å¯ç›´æŽ¥è¿è¡ŒéªŒè¯åŠŸèƒ½ã€‚ + +ä¾èµ–åˆç†åŸºäºŽ HashMap 实现,性能高效,适åˆç¼“存场景。 + +### 三ã€ä»£ç å­˜åœ¨çš„问题 + +è¿™äº›ä¸æ˜¯é”™è¯¯ï¼Œåªæ˜¯ä¸å¤Ÿè§„范: + +没有对 null åšå®‰å…¨å¤„ç† + +å…许存入 null é”® / 值 + +èŽ·å–æ—¶å¯èƒ½è¿”回 null,外部使用容易空指针 + +→ 建议增加éžç©ºæ ¡éªŒ + +线程ä¸å®‰å…¨HashMap 是éžçº¿ç¨‹å®‰å…¨çš„,多线程环境下会出现数æ®é”™è¯¯ã€‚ + +没有最大容é‡é™åˆ¶æ— ç¼“存上é™ï¼Œä¸æ–­å­˜å…¥ä¼šå¯¼è‡´å†…å­˜å ç”¨è¿‡é«˜ã€‚ + +无过期策略真实缓存都有过期时间,当å‰ä»£ç æ•°æ®æ°¸ä¹…ä¿å­˜ã€‚ + +缺少 toString () æ–¹æ³•æ— æ³•ç›´æŽ¥æ‰“å°æŸ¥çœ‹ç¼“å­˜å†…å®¹ï¼Œè°ƒè¯•ä¸æ–¹ä¾¿ã€‚ + +### å››ã€æ”¹è¿›åŽçš„ä¼˜åŒ–ä»£ç  + +import java.util.HashMap; + +import java.util.Map; + +import java.util.Objects; + + + +public class Cache { + + private final Map cacheMap; + + + + public Cache() { + + this.cacheMap = new HashMap<>(); + + } + + + + // 存入缓存(增加éžç©ºåˆ¤æ–­ï¼‰ + + public void put(K key, V value) { + + Objects.requireNonNull(key, "é”®ä¸èƒ½ä¸ºç©º"); + + Objects.requireNonNull(value, "值ä¸èƒ½ä¸ºç©º"); + + cacheMap.put(key, value); + + } + + + + // 获å–缓存 + + public V get(K key) { + + return cacheMap.get(key); + + } + + + + // 删除 + + public void remove(K key) { + + cacheMap.remove(key); + + } + + + + // 是å¦åŒ…å« + + public boolean containsKey(K key) { + + return cacheMap.containsKey(key); + + } + + + + // 清空 + + public void clear() { + + cacheMap.clear(); + + } + + + + // å¤§å° + + public int size() { + + return cacheMap.size(); + + } + + + + // 打å°ç¼“存内容 + + @Override + + public String toString() { + + return "Cache{" + "data=" + cacheMap + '}'; + + } + + + + // 测试 + + public static void main(String\[] args) { + + Cache studentScoreCache = new Cache<>(); + + + + studentScoreCache.put("张三", 90); + + studentScoreCache.put("æŽå››", 85); + + studentScoreCache.put("王五", 95); + + + + System.out.println(studentScoreCache); + + System.out.println("张三的分数:" + studentScoreCache.get("张三")); + + System.out.println("缓存大å°ï¼š" + studentScoreCache.size()); + + + + studentScoreCache.remove("æŽå››"); + + System.out.println("删除æŽå››åŽï¼š" + studentScoreCache); + + + + studentScoreCache.clear(); + + System.out.println("清空åŽç¼“存大å°ï¼š" + studentScoreCache.size()); + + } + +} +