[java 21 scopevalue(preview) 特定作用域數據共享 v01]
package com.hugh.java17.v21;
import java.lang.ScopedValue;
public class ScopeValueTest {
// 定義一個作用域值(類似“上下文的key”)
private static final ScopedValue<String> GIFT = ScopedValue.newInstance();
// 贈送禮物的方法:綁定值并執行接收邏輯
public static void giveGift() {
// 綁定 GIFT 的值為“手機”,并在作用域內執行 receiveGift()
ScopedValue.where(GIFT, "手機").run(() -> receiveGift());
}
// 接收禮物的方法:從作用域中獲取值
public static void receiveGift() {
// 獲取當前作用域內 GIFT 的值
String gift = GIFT.get();
System.out.println("收到禮物:" + gift); // 輸出:收到禮物:手機
}
public static void main(String[] args) {
giveGift(); // 調用贈送方法,觸發整個流程
}
}
代碼理解
ScopedValue Java 中的作用域值,用于在限定作用域內傳遞上下文信息
ScopedValue.where(...).run(...) 的設計看起來確實和“投放后隨時取用”的直覺不太一樣,但這恰恰是它的核心特性——嚴格限定作用域。我們可以從“為什么不能分開寫”和“這種設計的好處”兩個角度來理解:
1. 為什么不能把 where 和 run 分開?
假設我們嘗試“先投放再取用”,比如:
// 錯誤示例:嘗試分開寫
ScopedValue.where(GIFT, "手機"); // 假設這里只是“投放”
receiveGift(); // 再調用“取用”
這種寫法會失效,因為 ScopedValue 的核心是 “綁定值只在 run 方法執行的代碼塊內有效”。where 方法本身并不直接“投放”值,而是創建一個“綁定描述”,必須通過 run(或 call)來指定這個綁定生效的作用域范圍(即 run 里的 Lambda 表達式)。
離開這個作用域后,綁定自動失效。這就像“臨時借東西”:where 是“準備好要借的東西”,run 是“指定借東西的時間段和用途”,時間段外東西就還回去了。
2. 這種設計的好處:避免“全局污染”
如果允許“投放后隨時取用”,就會變成類似全局變量的效果:
- 不同地方的代碼可能意外修改或讀取到不該訪問的值;
- 多線程環境下,線程 A 的綁定可能被線程 B 誤讀,導致混亂。
而 where(...).run(...) 的設計強制要求:
- 綁定的生效范圍精確可控(就是
run里的代碼); - 超出范圍后自動失效,不會影響其他代碼;
- 多線程安全:每個線程的
run作用域是獨立的,互不干擾。
3. 換個角度理解:它像一個“帶參數的代碼塊”
可以把 ScopedValue.where(GIFT, "手機").run(()->{...}) 理解為:
“執行
{...}里的代碼時,給它傳一個‘隱藏參數’GIFT = "手機",這個參數只在{...}里能用。”
而 receiveGift() 就是這個代碼塊里的邏輯,它通過 GIFT.get() 拿到了這個“隱藏參數”。
這種方式比直接傳參更靈活(比如多層嵌套調用時,不需要每層方法都顯式聲明參數),但又比全局變量更安全(嚴格限定范圍)。
總結來說,run 方法的作用是劃定綁定生效的“生命周期”,這正是 ScopedValue 區別于全局變量或普通參數傳遞的關鍵——既解決了上下文傳遞的問題,又避免了全局污染。習慣這種“綁定+范圍”的組合寫法后,就能體會到它在復雜場景(如多線程、多層調用)中的優勢了。

浙公網安備 33010602011771號