Java函數(shù)作為參數(shù)的傳遞與使用常見問(wèn)題及避坑指南
Java中“函數(shù)作為參數(shù)傳遞”是實(shí)現(xiàn)“行為參數(shù)化”的核心方式,它能讓代碼更靈活、復(fù)用性更強(qiáng),與C、Python等語(yǔ)言直接傳遞函數(shù)不同,Java通過(guò)“接口+實(shí)現(xiàn)類”的方式間接實(shí)現(xiàn)這一功能,尤其在Java 8引入Lambda表達(dá)式后,寫法更加簡(jiǎn)潔。
一、為什么需要“函數(shù)作為參數(shù)”?
在傳統(tǒng)編程中,若要實(shí)現(xiàn)“相似邏輯但不同行為”的功能,往往需要重復(fù)編寫代碼。例如:實(shí)現(xiàn)一個(gè)“數(shù)組處理”工具,既能過(guò)濾出偶數(shù),又能過(guò)濾出大于10的數(shù)。
1.1 傳統(tǒng)方式的問(wèn)題(代碼冗余)
/**
* 傳統(tǒng)方式:過(guò)濾數(shù)組
* 問(wèn)題:邏輯相似但行為不同時(shí),需重復(fù)編寫代碼
*/
public class ArrayHandler {
// 過(guò)濾偶數(shù)
public static int[] filterEvenNumbers(int[] array) {
int[] result = new int[array.length];
int index = 0;
for (int num : array) {
if (num % 2 == 0) { // 核心判斷:偶數(shù)
result[index++] = num;
}
}
return Arrays.copyOf(result, index);
}
// 過(guò)濾大于10的數(shù)
public static int[] filterNumbersGreaterThan10(int[] array) {
int[] result = new int[array.length];
int index = 0;
for (int num : array) {
if (num > 10) { // 核心判斷:大于10
result[index++] = num;
}
}
return Arrays.copyOf(result, index);
}
}問(wèn)題分析:
- 兩段代碼的“框架邏輯”(遍歷數(shù)組、存儲(chǔ)結(jié)果)完全相同,僅“判斷條件”不同;
- 若需要新增過(guò)濾規(guī)則(如過(guò)濾質(zhì)數(shù)),需再寫一個(gè)幾乎相同的方法,代碼冗余嚴(yán)重;
- 維護(hù)成本高:若框架邏輯需要修改(如優(yōu)化存儲(chǔ)方式),所有方法都要同步修改。
1.2 “函數(shù)作為參數(shù)”的優(yōu)勢(shì)
若能將“判斷邏輯”作為參數(shù)傳遞給框架方法,就能避免重復(fù)代碼。例如:
// 框架方法:接收“判斷邏輯”作為參數(shù)
public static int[] filter(int[] array, FilterRule rule) {
// 框架邏輯(遍歷、存儲(chǔ))
int[] result = new int[array.length];
int index = 0;
for (int num : array) {
if (rule.test(num)) { // 調(diào)用傳遞進(jìn)來(lái)的“判斷邏輯”
result[index++] = num;
}
}
return Arrays.copyOf(result, index);
}使用時(shí)只需傳遞不同的“判斷邏輯”:
// 過(guò)濾偶數(shù):傳遞“偶數(shù)判斷”邏輯 int[] evens = filter(array, num -> num % 2 == 0); // 過(guò)濾大于10的數(shù):傳遞“大于10判斷”邏輯 int[] greaterThan10 = filter(array, num -> num > 10);
核心優(yōu)勢(shì):
- 行為參數(shù)化:框架邏輯固定,行為(如判斷條件)通過(guò)參數(shù)動(dòng)態(tài)傳入;
- 代碼復(fù)用:框架方法只需寫一次,不同行為通過(guò)參數(shù)擴(kuò)展;
- 靈活性高:新增功能時(shí)無(wú)需修改原有代碼,只需新增“行為實(shí)現(xiàn)”;
- 可讀性強(qiáng):通過(guò)Lambda表達(dá)式,行為邏輯一目了然。
二、Java中函數(shù)傳遞的核心:函數(shù)式接口
Java是“面向?qū)ο?rdquo;語(yǔ)言,無(wú)法直接傳遞函數(shù),但可以通過(guò)“接口+實(shí)現(xiàn)類”的方式間接傳遞——將函數(shù)邏輯封裝到接口的實(shí)現(xiàn)類中,再將實(shí)現(xiàn)類對(duì)象作為參數(shù)傳遞。
2.1 函數(shù)式接口的定義
能用于“函數(shù)傳遞”的接口必須是“函數(shù)式接口”——即只包含一個(gè)抽象方法的接口(可包含默認(rèn)方法、靜態(tài)方法)。這種接口的實(shí)例可以代表一個(gè)“函數(shù)”。
/**
* 函數(shù)式接口示例:定義“過(guò)濾規(guī)則”
* 只包含一個(gè)抽象方法test,用于封裝“判斷邏輯”
*/
@FunctionalInterface // 標(biāo)記為函數(shù)式接口(可選,編譯器會(huì)校驗(yàn))
interface FilterRule {
// 抽象方法:接收int參數(shù),返回boolean(判斷結(jié)果)
boolean test(int num);
// 允許包含默認(rèn)方法(非抽象)
default void printRule() {
System.out.println("執(zhí)行過(guò)濾規(guī)則");
}
}關(guān)鍵說(shuō)明:
@FunctionalInterface注解是可選的,但加上后編譯器會(huì)強(qiáng)制檢查接口是否符合“只有一個(gè)抽象方法”的規(guī)則;- 函數(shù)式接口的抽象方法簽名(參數(shù)+返回值)決定了“可傳遞的函數(shù)類型”(如
FilterRule可傳遞“接收int、返回boolean”的函數(shù))。
2.2 通過(guò)“接口實(shí)現(xiàn)類”傳遞函數(shù)
早期Java(8之前)通過(guò)“匿名內(nèi)部類”實(shí)現(xiàn)函數(shù)傳遞,步驟如下:
步驟1:定義函數(shù)式接口
// 函數(shù)式接口:封裝“字符串處理”邏輯
@FunctionalInterface
interface StringProcessor {
String process(String str);
}
步驟2:編寫接收接口參數(shù)的方法
/**
* 框架方法:接收StringProcessor對(duì)象(封裝了處理邏輯)
*/
public static String handleString(String str, StringProcessor processor) {
// 調(diào)用接口方法(執(zhí)行傳遞進(jìn)來(lái)的函數(shù)邏輯)
return processor.process(str);
}
步驟3:通過(guò)匿名內(nèi)部類傳遞函數(shù)邏輯
public static void main(String[] args) {
String str = " hello world ";
// 1. 傳遞“去除空格”邏輯(匿名內(nèi)部類)
String trimmed = handleString(str, new StringProcessor() {
@Override
public String process(String s) {
return s.trim(); // 去除首尾空格
}
});
// 2. 傳遞“轉(zhuǎn)大寫”邏輯(匿名內(nèi)部類)
String upper = handleString(str, new StringProcessor() {
@Override
public String process(String s) {
return s.toUpperCase(); // 轉(zhuǎn)為大寫
}
});
System.out.println(trimmed); // 輸出:hello world
System.out.println(upper); // 輸出: HELLO WORLD
}原理:匿名內(nèi)部類的process方法實(shí)現(xiàn)了具體的函數(shù)邏輯,將該對(duì)象作為參數(shù)傳遞給handleString,就相當(dāng)于傳遞了process方法中的邏輯。
2.3 Java 8+:通過(guò)Lambda表達(dá)式簡(jiǎn)化傳遞
Java 8引入的Lambda表達(dá)式可以簡(jiǎn)化函數(shù)式接口實(shí)現(xiàn)類的創(chuàng)建,無(wú)需編寫匿名內(nèi)部類的冗余代碼。
Lambda表達(dá)式的基本語(yǔ)法
(參數(shù)列表) -> { 函數(shù)體 }- 若參數(shù)只有一個(gè),可省略參數(shù)列表的括號(hào)(如
num -> num % 2 == 0); - 若函數(shù)體只有一行代碼,可省略大括號(hào)和
return(自動(dòng)返回結(jié)果); - 類型可省略(編譯器自動(dòng)推斷)。
使用Lambda傳遞函數(shù)
用Lambda表達(dá)式簡(jiǎn)化上述StringProcessor的使用:
public static void main(String[] args) {
String str = " hello world ";
// 1. 傳遞“去除空格”邏輯(Lambda簡(jiǎn)化)
String trimmed = handleString(str, s -> s.trim());
// 2. 傳遞“轉(zhuǎn)大寫”邏輯(Lambda簡(jiǎn)化)
String upper = handleString(str, s -> s.toUpperCase());
// 3. 復(fù)雜邏輯(多行代碼):需加{}和return
String processed = handleString(str, s -> {
String temp = s.trim();
return temp.substring(0, 5); // 截取前5個(gè)字符
});
System.out.println(processed); // 輸出:hello
}對(duì)比匿名內(nèi)部類與Lambda:
- 匿名內(nèi)部類:代碼冗余,但兼容性好(支持所有Java版本);
- Lambda表達(dá)式:代碼簡(jiǎn)潔(一行搞定),僅支持Java 8及以上。
三、Java內(nèi)置的函數(shù)式接口
Java 8在java.util.function包中提供了常用的函數(shù)式接口,無(wú)需自定義即可直接使用,覆蓋大部分函數(shù)場(chǎng)景。
3.1 四大核心函數(shù)式接口
| 接口名 | 抽象方法 | 功能描述 | 示例場(chǎng)景 |
|---|---|---|---|
Consumer<T> | void accept(T t) | 接收T類型參數(shù),無(wú)返回值(消費(fèi)數(shù)據(jù)) | 打印數(shù)據(jù)、修改對(duì)象屬性 |
Supplier<T> | T get() | 無(wú)參數(shù),返回T類型結(jié)果(提供數(shù)據(jù)) | 生成隨機(jī)數(shù)、創(chuàng)建對(duì)象 |
Function<T,R> | R apply(T t) | 接收T類型參數(shù),返回R類型結(jié)果 | 數(shù)據(jù)轉(zhuǎn)換(如String→Integer) |
Predicate<T> | boolean test(T t) | 接收T類型參數(shù),返回boolean(判斷) | 過(guò)濾數(shù)據(jù)、條件校驗(yàn) |
3.2 內(nèi)置接口的使用示例
3.2.1 Consumer:消費(fèi)數(shù)據(jù)
用于“接收數(shù)據(jù)并處理(無(wú)返回值)”,如打印、存儲(chǔ)等。
import java.util.function.Consumer;
public class ConsumerDemo {
// 框架方法:接收數(shù)據(jù)和處理邏輯
public static void processData(String data, Consumer<String> consumer) {
consumer.accept(data); // 執(zhí)行傳遞的處理邏輯
}
public static void main(String[] args) {
// 1. 傳遞“打印數(shù)據(jù)”邏輯
processData("hello", s -> System.out.println("打?。? + s));
// 2. 傳遞“拼接前綴”邏輯(無(wú)返回值,僅處理)
processData("world", s -> {
String result = "前綴_" + s;
System.out.println("處理后:" + result);
});
}
}3.2.2 Function<T,R>:數(shù)據(jù)轉(zhuǎn)換
用于“接收一種類型數(shù)據(jù),返回另一種類型數(shù)據(jù)”,如類型轉(zhuǎn)換、格式處理。
import java.util.function.Function;
public class FunctionDemo {
// 框架方法:接收數(shù)據(jù)和轉(zhuǎn)換邏輯
public static <R> R transform(String data, Function<String, R> function) {
return function.apply(data); // 執(zhí)行轉(zhuǎn)換邏輯
}
public static void main(String[] args) {
// 1. 轉(zhuǎn)換為Integer(字符串轉(zhuǎn)數(shù)字)
Integer num = transform("123", s -> Integer.parseInt(s));
// 2. 轉(zhuǎn)換為長(zhǎng)度(字符串→整數(shù))
Integer length = transform("hello", s -> s.length());
// 3. 轉(zhuǎn)換為大寫(字符串→字符串)
String upper = transform("hello", s -> s.toUpperCase());
}
}3.2.3 Predicate:條件判斷
用于“接收數(shù)據(jù)并返回布爾值”,如過(guò)濾、校驗(yàn)。
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class PredicateDemo {
// 框架方法:過(guò)濾集合
public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
List<T> result = new ArrayList<>();
for (T item : list) {
if (predicate.test(item)) { // 執(zhí)行判斷邏輯
result.add(item);
}
}
return result;
}
public static void main(String[] args) {
List<String> list = List.of("a", "bb", "ccc", "dddd");
// 1. 過(guò)濾長(zhǎng)度>2的字符串
List<String> longStrs = filter(list, s -> s.length() > 2);
System.out.println(longStrs); // 輸出:[ccc, dddd]
// 2. 過(guò)濾包含"c"的字符串
List<String> hasC = filter(list, s -> s.contains("c"));
System.out.println(hasC); // 輸出:[ccc]
}
}3.3 其他常用接口
除四大核心接口外,Java還提供了針對(duì)基本類型的接口(避免自動(dòng)裝箱)和雙參數(shù)接口:
| 接口名 | 抽象方法 | 功能描述 |
|---|---|---|
IntConsumer | void accept(int value) | 接收int參數(shù)(避免int→Integer裝箱) |
LongPredicate | boolean test(long value) | 接收l(shuí)ong參數(shù),返回boolean |
BiFunction<T,U,R> | R apply(T t, U u) | 接收兩個(gè)參數(shù)(T和U),返回R |
BiConsumer<T,U> | void accept(T t, U u) | 接收兩個(gè)參數(shù),無(wú)返回值 |
四、實(shí)戰(zhàn):函數(shù)作為參數(shù)的典型應(yīng)用場(chǎng)景
4.1 集合處理(過(guò)濾、轉(zhuǎn)換)
集合的遍歷、過(guò)濾、轉(zhuǎn)換是函數(shù)傳遞的高頻場(chǎng)景,Java 8的StreamAPI大量使用了這種方式。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 17),
new User("王五", 25)
);
// 1. 過(guò)濾成年用戶(年齡≥18):傳遞Predicate<User>
List<User> adults = users.stream()
.filter(user -> user.getAge() >= 18) // 傳遞過(guò)濾邏輯
.collect(Collectors.toList());
// 2. 提取用戶名(轉(zhuǎn)換為String列表):傳遞Function<User,String>
List<String> names = users.stream()
.map(user -> user.getName()) // 傳遞轉(zhuǎn)換邏輯
.collect(Collectors.toList());
// 3. 打印用戶信息:傳遞Consumer<User>
users.forEach(user -> System.out.println(user.getName() + ":" + user.getAge()));
}
// 實(shí)體類
static class User {
private String name;
private int age;
// 構(gòu)造器、getter
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
}4.2 事件監(jiān)聽(回調(diào)函數(shù))
在GUI編程或異步處理中,“回調(diào)函數(shù)”(事件發(fā)生時(shí)執(zhí)行的邏輯)通常通過(guò)函數(shù)傳遞實(shí)現(xiàn)。
import java.util.Scanner;
/**
* 模擬按鈕點(diǎn)擊事件:點(diǎn)擊后執(zhí)行傳遞的邏輯
*/
public class EventDemo {
// 按鈕類:接收“點(diǎn)擊事件處理邏輯”
static class Button {
// 存儲(chǔ)回調(diào)函數(shù)(點(diǎn)擊時(shí)執(zhí)行)
private Runnable onClick;
// 設(shè)置點(diǎn)擊事件邏輯(接收Runnable函數(shù)式接口)
public void setOnClick(Runnable onClick) {
this.onClick = onClick;
}
// 模擬點(diǎn)擊(觸發(fā)回調(diào))
public void click() {
if (onClick != null) {
onClick.run(); // 執(zhí)行傳遞的邏輯
}
}
}
public static void main(String[] args) {
Button button = new Button();
// 設(shè)置點(diǎn)擊邏輯(傳遞Runnable函數(shù))
button.setOnClick(() -> {
System.out.println("按鈕被點(diǎn)擊!");
System.out.println("執(zhí)行提交表單邏輯...");
});
// 模擬用戶點(diǎn)擊
System.out.println("請(qǐng)輸入任意字符模擬點(diǎn)擊:");
new Scanner(System.in).next(); // 等待輸入
button.click(); // 輸出點(diǎn)擊邏輯
}
}4.3 通用工具類(行為參數(shù)化)
編寫通用工具時(shí),通過(guò)函數(shù)傳遞行為可大幅提升工具的靈活性。例如:定義一個(gè)“數(shù)據(jù)校驗(yàn)工具”,支持不同校驗(yàn)規(guī)則。
import java.util.function.Predicate;
/**
* 通用校驗(yàn)工具:支持不同校驗(yàn)規(guī)則
*/
public class Validator<T> {
// 校驗(yàn)數(shù)據(jù):接收數(shù)據(jù)和校驗(yàn)規(guī)則
public boolean validate(T data, Predicate<T> rule) {
return rule.test(data);
}
public static void main(String[] args) {
Validator<String> stringValidator = new Validator<>();
// 1. 校驗(yàn)字符串非空
boolean notEmpty = stringValidator.validate("test", s -> s != null && !s.isEmpty());
// 2. 校驗(yàn)字符串長(zhǎng)度≥6
boolean minLength6 = stringValidator.validate("123456", s -> s.length() >= 6);
// 3. 校驗(yàn)手機(jī)號(hào)(簡(jiǎn)單規(guī)則)
boolean isPhone = stringValidator.validate("13800138000",
s -> s.matches("1[3-9]\\d{9}"));
}
}五、常見問(wèn)題與避坑指南
5.1 函數(shù)式接口必須“只有一個(gè)抽象方法”
錯(cuò)誤:定義的接口包含多個(gè)抽象方法,無(wú)法用Lambda表達(dá)式實(shí)例化。
// 錯(cuò)誤:包含兩個(gè)抽象方法,不是函數(shù)式接口
interface MyInterface {
void method1();
void method2(); // 第二個(gè)抽象方法
}
// 編譯報(bào)錯(cuò):Lambda表達(dá)式無(wú)法匹配多個(gè)抽象方法
MyInterface obj = () -> System.out.println("test");解決方案:確保接口只有一個(gè)抽象方法,多余的方法可改為默認(rèn)方法或靜態(tài)方法。
5.2 Lambda表達(dá)式中變量的“有效final”
Lambda表達(dá)式中引用的外部變量必須是“有效final”(即聲明后未被修改)。
public class LambdaVariableDemo {
public static void main(String[] args) {
int count = 0; // 外部變量
// 錯(cuò)誤:在Lambda中修改外部變量
Runnable runnable = () -> {
count++; // 編譯報(bào)錯(cuò):變量count必須是final或有效final
};
}
}原因:Lambda表達(dá)式可能在另一個(gè)線程中執(zhí)行,變量修改會(huì)導(dǎo)致線程安全問(wèn)題。
解決方案:
- 若需修改變量,可使用原子類(如
AtomicInteger); - 將變量封裝到對(duì)象中,修改對(duì)象的屬性(對(duì)象引用不變)。
5.3 避免過(guò)度使用Lambda導(dǎo)致可讀性下降
Lambda表達(dá)式適合簡(jiǎn)短邏輯(1-2行代碼),復(fù)雜邏輯若用Lambda會(huì)降低可讀性。
// 不推薦:復(fù)雜邏輯用Lambda,可讀性差
Function<String, String> complexFunction = s -> {
String temp = s.trim();
if (temp.length() > 10) {
temp = temp.substring(0, 10);
}
return temp.toUpperCase();
};
解決方案:復(fù)雜邏輯建議用單獨(dú)的方法實(shí)現(xiàn),再通過(guò)方法引用傳遞。
// 推薦:復(fù)雜邏輯單獨(dú)定義
public static String processString(String s) {
String temp = s.trim();
if (temp.length() > 10) {
temp = temp.substring(0, 10);
}
return temp.toUpperCase();
}
// 通過(guò)方法引用傳遞(::表示引用方法)
Function<String, String> complexFunction = LambdaDemo::processString;5.4 方法引用的正確使用
方法引用(類名::方法名)是Lambda的簡(jiǎn)化寫法,但需確保方法簽名與函數(shù)式接口的抽象方法匹配。
// 函數(shù)式接口:接收String,返回int
interface StringToInt {
int convert(String s);
}
public class MethodReferenceDemo {
// 方法:簽名(String→int)與StringToInt匹配
public static int stringToLength(String s) {
return s.length();
}
public static void main(String[] args) {
// 方法引用:直接引用stringToLength方法
StringToInt converter = MethodReferenceDemo::stringToLength;
int length = converter.convert("hello"); // 輸出:5
}
}注意:方法引用的方法參數(shù)類型、返回值類型必須與函數(shù)式接口的抽象方法完全匹配。
總結(jié)
- 代碼靈活性:通過(guò)傳遞不同函數(shù),動(dòng)態(tài)改變方法的行為,無(wú)需修改原有邏輯;
- 代碼復(fù)用:框架方法只需實(shí)現(xiàn)一次,行為通過(guò)參數(shù)擴(kuò)展;
- 可讀性提升:Lambda表達(dá)式讓行為邏輯直觀可見,代碼更簡(jiǎn)潔;
- 符合開閉原則:新增功能時(shí)無(wú)需修改原有代碼,只需新增函數(shù)實(shí)現(xiàn)。
從早期的匿名內(nèi)部類到Java 8的Lambda表達(dá)式,函數(shù)傳遞的寫法越來(lái)越簡(jiǎn)潔,但核心原理始終是“函數(shù)式接口+實(shí)現(xiàn)類”,實(shí)際開發(fā)中,應(yīng)優(yōu)先使用Java內(nèi)置的函數(shù)式接口(如Predicate、Function),避免重復(fù)定義;復(fù)雜邏輯建議單獨(dú)定義方法,通過(guò)方法引用傳遞,平衡簡(jiǎn)潔性和可讀性。
到此這篇關(guān)于Java函數(shù)作為參數(shù)的傳遞與使用常見問(wèn)題及避坑指南的文章就介紹到這了,更多相關(guān)java函數(shù)參數(shù)傳遞內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot配置logback.xml 多環(huán)境的操作步驟
最近在研究springboot的日志,所以記錄一下,做一下總結(jié),今天重點(diǎn)給大家介紹SpringBoot配置logback.xml 多環(huán)境的操作步驟,要實(shí)現(xiàn)多環(huán)境的配置,主要是依賴于springboot的application.yml文件去實(shí)現(xiàn),感興趣的朋友跟隨小編一起看看吧2021-05-05
詳解SpringSecurity如何實(shí)現(xiàn)前后端分離
這篇文章主要為大家介紹了詳解SpringSecurity如何實(shí)現(xiàn)前后端分離,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Spring Boot啟動(dòng)過(guò)程完全解析(一)
這篇文章主要介紹了Spring Boot啟動(dòng)過(guò)程完全解析(一),需要的朋友可以參考下2017-04-04
Spring注解@EnableWebMvc使用的坑點(diǎn)及解析
這篇文章主要介紹了Spring注解@EnableWebMvc使用的坑點(diǎn)及解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
myBatis實(shí)現(xiàn)三級(jí)嵌套復(fù)雜對(duì)象的賦值問(wèn)題
這篇文章主要介紹了myBatis實(shí)現(xiàn)三級(jí)嵌套復(fù)雜對(duì)象的賦值問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11
SpringAI流式輸出的底層實(shí)現(xiàn)原理解析
在 Spring AI 中,流式輸出(Streaming Output)是一種逐步返回 AI 模型生成結(jié)果的技術(shù),允許服務(wù)器將響應(yīng)內(nèi)容分批次實(shí)時(shí)傳輸給客戶端,而不是等待全部?jī)?nèi)容生成完畢后再一次性返回,這篇文章主要介紹了SpringAI流式輸出的底層實(shí)現(xiàn),需要的朋友可以參考下2025-04-04

