Spring提供的SPEL表達式

SPEL

1. 概述

SpEL是Spring框架中用于表達式語言的一種方式。它類似于其他編程語言中的表達式語言,用于在運行時計算值或執行特定任務。
SpEL提供了一種簡單且強大的方式來訪問和操作對象的屬性、調用對象的方法,以及實現運算、條件判斷等操作。它可以被用于XML和注解配置中,可以用于許多Spring框架中的特性,如依賴注入、AOP、配置文件等。
SpEL表達式可以在字符串中進行定義,使用特殊的語法和符號來表示特定的操作。例如,可以使用${expression}來表示一個SpEL表達式,其中expression是具體的SpEL語句。
SpEL支持各種操作和函數,包括算術運算、邏輯運算、條件判斷、正則表達式匹配、集合操作等。它還支持訪問上下文中的變量和參數,以及調用對象的方法

2. 基礎語法學習案例


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.*;/*** SPEL表達式案例** @author xuyuan* @see EvaluationContext* @see SimpleEvaluationContext 定制化提供特定的上下文對象,控制讀寫權限,可以只讀如下的SimpleEvaluationContext.forReadOnlyDataBinding().build()* SimpleEvaluationContext.forReadOnlyDataBinding().build():* 適用于簡單的、只讀的數據綁定場景。* 性能較好,但功能有限。* 不支持復雜的表達式操作。* <p>* new StandardEvaluationContext(obj):* 適用于復雜的表達式求值場景。* 功能全面,支持所有SPEL特性。* 可以設置根對象和其他上下文信息,靈活性高。*/
public class SpelExam {/*** 操作字面量*/@Testpublic void test() {ExpressionParser parser = new SpelExpressionParser();// 獲取字符串 "Hello World"String helloWorld = parser.parseExpression("'Hello World'").getValue(String.class);System.out.println(helloWorld);// double類型 6.0221415E23double avogadrosNumber = parser.parseExpression("6.0221415E+23").getValue(Double.class);System.out.println(avogadrosNumber);// int類型 2147483647int maxValue = parser.parseExpression("0x7FFFFFFF").getValue(Integer.class);System.out.println(maxValue);// trueboolean trueValue = parser.parseExpression("true").getValue(Boolean.class);System.out.println(trueValue);// nullObject nullValue = parser.parseExpression("null").getValue();System.out.println(nullValue);}/*** 操作對象*/@Testpublic void test2() {// 定義Parser,可以定義全局的parserExpressionParser parser = new SpelExpressionParser();// 注意!屬性名的第一個字母不區分大小寫。 birthdate.year等效于Birthdate.Year// 取出Inventor 中,birthdate屬性的year屬性Inventor zhangsan = new Inventor("zhangsan", new Date(), "China");// 定義StandardEvaluationContext ,傳入一個操作對象StandardEvaluationContext zhangsanContext = new StandardEvaluationContext(zhangsan);int year = parser.parseExpression("birthdate.year + 1900").getValue(zhangsanContext, Integer.class);System.out.println(year); // 2025// 取出Inventor的placeOfBirth的city屬性PlaceOfBirth placeOfBirth = new PlaceOfBirth("長沙", "中國");zhangsan.setPlaceOfBirth(placeOfBirth);String city = parser.parseExpression("placeOfBirth.City").getValue(zhangsanContext, String.class);System.out.println(city); // 長沙}/*** 操作數組和List*/@Testpublic void test3() {// 定義Parser,可以定義全局的parserExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();// 省略數據初始化Society ieee = new Society();Inventor tesla = new Inventor("Tesla", "USA");ieee.getMembers().add(tesla);ieee.getMembers().add(new Inventor("BYD", "CN"));ieee.getMembers().add(new Inventor("BMW", "GE"));ieee.getMembers().add(new Inventor("FLL", "FR"));tesla.setInventions(new String[]{"Lightning", "Telephone", "Computer", "Electricity", "Electric Motor", "Electric Engine", "Electric Car"});String value = parser.parseExpression("inventions[3]").getValue(context, tesla, String.class);System.out.println("取出tesla對象的inventions 第四個數據:" + value);String name = parser.parseExpression("Members[0].Name").getValue(context, ieee, String.class);System.out.println("取出ieee對象的第一個Member的name屬性:" + name);String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(context, ieee, String.class);System.out.println("取出ieee對象的第一個Member的第七個Inventions:" + invention);}/*** 操作Map*/@Testpublic void test4() {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();Society ieee = new Society();ieee.getOfficers().put("president", new Inventor("Tesla", "USA"));ieee.getOfficers().put("advisors", new Inventor("BYD", "CN"));ieee.getOfficers().put("secretary", new Inventor("BMW", "GE"));ieee.getOfficers().put("treasurer", new Inventor("FLL", "FR"));String name = parser.parseExpression("officers['advisors'].name").getValue(context, ieee, String.class);System.out.println("取出ieee對象的advisors的name屬性:" + name);}/*** 內嵌List/Map*/@Testpublic void test5() {// 定義Parser,可以定義全局的parserExpressionParser parser = new SpelExpressionParser();// [1, 2, 3, 4]List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue();System.out.println(numbers);// 嵌套: [[a, b], [x, y]]List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue();System.out.println(listOfLists);// {name=Nikola, dob=10-July-1856}Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue();System.out.println(inventorInfo);// 嵌套:{name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue();System.out.println(mapOfMaps);// List與Map可以嵌套使用,互相結合。// 嵌套:[{name={first=Nikola, last=Tesla}}, {dob={day=10, month=July, year=1856}}]List listOfMaps = (List) parser.parseExpression("{{name:{first:'Nikola',last:'Tesla'}},{dob:{day:10,month:'July',year:1856}}}").getValue();System.out.println(listOfMaps);}/*** 構建數組*/@Testpublic void test6() {ExpressionParser parser = new SpelExpressionParser();int[] numbers1 = parser.parseExpression("new int[4]").getValue(int[].class);// 數組并初始化int[] numbers2 = parser.parseExpression("new int[]{1,2,3}").getValue(int[].class);// 多維數組int[][] numbers3 = parser.parseExpression("new int[4][5]").getValue(int[][].class);}/*** 調用方法*/@Testpublic void test7() {ExpressionParser parser = new SpelExpressionParser();// 調用substring方法System.out.println(parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class));// 調用societyContext中對象的isMember方法,并傳值。StandardEvaluationContext societyContext = new StandardEvaluationContext(new Society());boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);}/*** 關系運算* 每個符號操作符也可以被指定為純字母的等價物。這避免了所使用的符號對于嵌入表達式的文檔類型具有特殊含義的問題(例如在XML文檔中)。所有文本操作符都不區分大小寫。對應的文本是:* lt (<)* gt (>)* le (<=)* ge (>=)* eq (==)* ne (!=)* div (/)* mod (%)* not (!)*/@Testpublic void test8() {ExpressionParser parser = new SpelExpressionParser();boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);boolean trueValue1 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);}/*** instanceof 和 正則表達式的匹配操作符* 使用基本類型時要小心,因為它們會立即被裝箱為包裝器類型,所以1 instanceof T(int)會計算為false,而1 instanceof T(Integer)會計算為true。*/@Testpublic void test9() {ExpressionParser parser = new SpelExpressionParser();boolean value = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);boolean trueValue = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);boolean falseValue = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);}/*** 邏輯運算符:and, or, not*/@Testpublic void test10() {ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext societyContext = new StandardEvaluationContext(new Society());boolean value = parser.parseExpression("true and false").getValue(Boolean.class);String expression1 = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";boolean value1 = parser.parseExpression(expression1).getValue(societyContext, Boolean.class);boolean value2 = parser.parseExpression("true or false").getValue(Boolean.class);String expression2 = "isMember('Nikola Tesla') or isMember('Albert Einstein')";boolean valu3 = parser.parseExpression(expression2).getValue(societyContext, Boolean.class);boolean value4 = parser.parseExpression("!true").getValue(Boolean.class);String expression3 = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";boolean value5 = parser.parseExpression(expression3).getValue(societyContext, Boolean.class);}/*** 數學計算符*/@Testpublic void test11() {ExpressionParser parser = new SpelExpressionParser();parser.parseExpression("1 + 1").getValue(Integer.class);  // 2parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class);  // 'test string'parser.parseExpression("1 - -3").getValue(Integer.class);  // 4parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6parser.parseExpression("6 / -3").getValue(Integer.class);  // -2parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0parser.parseExpression("7 % 4").getValue(Integer.class);  // 3parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21}/*** 類型獲取符:T()* T(Type):用于引用靜態類型。* T(Type).staticMethod():用于調用靜態方法。* T(Type).STATIC_FIELD:用于訪問靜態字段。* instanceof T(Type):用于類型檢查。*/@Testpublic void test12() {ExpressionParser parser = new SpelExpressionParser();Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);}/*** 調用構造函數*/@Testpublic void test13() {System.out.println(Inventor.class.getName());ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext societyContext = new StandardEvaluationContext(new Society());Inventor einstein = parser.parseExpression("new com.xuyuan.spring.spel.SpelExam.Inventor('Albert Einstein', 'German')").getValue(Inventor.class);// 創建一個新的Inventor,并且添加到members的list中parser.parseExpression("Members.add(com.xuyuan.spring.spel.SpelExam.Inventor('Albert Einstein', 'German'))").getValue(societyContext);System.out.println(societyContext.getRootObject().getValue());}/*** Spel變量* #variableName語法在表達式中引用變量*/@Testpublic void test14() {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();context.setVariable("newName", "Mike Tesla"); // 設置變量Inventor tesla = new Inventor("Nikola Tesla", "Serbian");// 獲取變量newName,并將其賦值給name屬性parser.parseExpression("Name = #newName").getValue(context, tesla);System.out.println(tesla.getName());  // "Mike Tesla"}/*** #this變量引用當前的評估對象(根據該評估對象解析非限定引用)。* #root變量總是被定義并引用根上下文對象。雖然#this可能會隨著表達式的組成部分的計算而變化,但是#root總是指根。*/@Testpublic void test15() {// 創建一個Integer數組List<Integer> primes = new ArrayList<Integer>();primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17));ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();context.setVariable("primes", primes);List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);System.out.println(primesGreaterThanTen);}/*** 三元表達式*/@Testpublic void test16() {ExpressionParser parser = new SpelExpressionParser();String expression = "10 > 5 ? 'ten is greater than five' : 'ten is not greater than five'";parser.parseExpression(expression).getValue(String.class);}/*** Elvis操作符*/@Testpublic void test17() {ExpressionParser parser = new SpelExpressionParser();String name = "Elvis Presley";String displayName = (name != null ? name : "Unknown");String name1 = parser.parseExpression("name?:'Unknown'").getValue(String.class);System.out.println(name1);  // 'Unknown'}/*** 安全導航運算符:obj?.prop* 安全導航操作符用于避免NullPointerException,來自Groovy語言。* 通常,當引用一個對象時,可能需要在訪問該對象的方法或屬性之前驗證它不為null。為了避免這種情況,安全導航運算符返回null,而不是引發異常。以下示例顯示了如何使用安全導航運算符*/@Testpublic void test18() {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();Inventor tesla = new Inventor("Nikola Tesla", "Serbian");tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan", "Croatia"));String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);System.out.println(city);  // Smiljantesla.setPlaceOfBirth(null);city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);System.out.println(city);  // null - does not throw NullPointerException!!!}/*** 集合選擇:?[predicate]*/@Testpublic void test19() {Society ieee = new Society();ieee.getMembers().add(new Inventor("Tesla", "USA"));ieee.getMembers().add(new Inventor("BYD", "CN"));ieee.getMembers().add(new Inventor("BMW", "GE"));ieee.getMembers().add(new Inventor("FLL", "FR"));ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext context = new StandardEvaluationContext(ieee);// 語法.?[selectionExpression]List<Inventor> list = parser.parseExpression("Members.?[Nationality == 'Serbian']").getValue(context, List.class);Map<String, Integer> map = new HashMap<>();context.setVariable("map", map);map.put("Tesla0", 28);map.put("Tesla1", 26);map.put("Tesla2", 25);// 返回value小于27的值// 使用參數化的 Map 類型Map<String, Integer> newMap = parser.parseExpression("#map.?[value < 27]").getValue(context, Map.class);System.out.println(newMap);  // 輸出符合條件的鍵值對}/*** 集合投影:![expression]*/@Testpublic void test20() {Society ieee = new Society();ieee.getMembers().add(new Inventor("Tesla", "USA"));ieee.getMembers().add(new Inventor("BYD", "CN"));ieee.getMembers().add(new Inventor("BMW", "GE"));ieee.getMembers().add(new Inventor("FLL", "FR"));ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext context = new StandardEvaluationContext(ieee);List placesOfBirth = parser.parseExpression("Members.![placeOfBirth?.city]").getValue(context, List.class);}/*** 表達式模板:#{expression}* 通常使用#{}作為模板,與字符串拼接*/@Testpublic void test21() {ExpressionParser parser = new SpelExpressionParser();// 通常使用#{}作為模板,與字符串拼接起來String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue(String.class);System.out.println(randomPhrase); // "random number is 0.7038186818312008"}@Data@AllArgsConstructor@NoArgsConstructorclass PlaceOfBirth {private String city;private String country;}@Data@AllArgsConstructor@NoArgsConstructorclass Society {private String name;public String Advisors = "advisors";public String President = "president";private List<Inventor> members = new ArrayList<>();private Map officers = new HashMap();public boolean isMember(String name) {for (Inventor inventor : members) {if (inventor.getName().equals(name)) {return true;}}return false;}}@Data@NoArgsConstructor@AllArgsConstructorclass Inventor {private String name;private String nationality;private String[] inventions;private Date birthdate;private PlaceOfBirth placeOfBirth;public Inventor(String name, String nationality) {GregorianCalendar c = new GregorianCalendar();this.name = name;this.nationality = nationality;this.birthdate = c.getTime();}public Inventor(String name, Date birthdate, String nationality) {this.name = name;this.nationality = nationality;this.birthdate = birthdate;}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/71588.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/71588.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/71588.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Azure 架構師學習筆記】- Azure Databricks (14) -- 搭建Medallion Architecture part 2

本文屬于【Azure 架構師學習筆記】系列。 本文屬于【Azure Databricks】系列。 接上文 【Azure 架構師學習筆記】- Azure Databricks (13) – 搭建Medallion Architecture part 1 前言 上文搭建了ADB 與外部的交互部分&#xff0c;本篇搭建ADB 內部配置來滿足medallion 架構。…

vulnhub靶場之【digitalworld.local系列】的torment靶機

前言 靶機&#xff1a;digitalworld.local-torment&#xff0c;IP地址為192.168.10.12 攻擊&#xff1a;kali&#xff0c;IP地址為192.168.10.6 kali采用VMware虛擬機&#xff0c;靶機選擇使用VMware打開文件&#xff0c;都選擇橋接網絡 這里官方給的有兩種方式&#xff0c…

docker-compose部署mongodb副本集集群

生成密鑰文件 ? openssl rand -base64 756 > mongodb.key chmod 400 mongodb.key # 權限必須為400?:ml-citation{ref="4" data="citationList"} chown 999:999 mongodb.key # MongoDB容器用戶ID為999?:ml-citation{ref="4" data="…

k8s v1.28.15部署(kubeadm方式)

k8s部署&#xff08;kubeadm方式&#xff09; 部署環境及版本 系統版本&#xff1a;CentOS Linux release 7.9.2009 k8s版本&#xff1a;v1.28.15 docker版本&#xff1a;26.1.4 containerd版本&#xff1a;1.6.33 calico版本&#xff1a;v3.25.0準備 主機ip主機名角色配置1…

Redis特性總結

一、速度快 正常情況下&#xff0c;Redis 執?命令的速度?常快&#xff0c;官?給出的數字是讀寫性能可以達到 10 萬 / 秒&#xff0c;當然這也取決于機器的性能&#xff0c;但這?先不討論機器性能上的差異&#xff0c;只分析?下是什么造就了 Redis 如此之快&#xff0c;可以…

C# Unity 面向對象補全計劃 之 索引器與迭代器

本文僅作學習筆記與交流&#xff0c;不作任何商業用途&#xff0c;作者能力有限&#xff0c;如有不足還請斧正 本篇有部分內容出自唐老獅,唐老師網站指路:全部 - 游習堂 - 唐老獅創立的游戲開發在線學習平臺 - Powered By EduSoho 目錄 1.索引器 2.迭代器 1.索引器 我的理解 索…

深度學習PyTorch之13種模型精度評估公式及調用方法

深度學習pytorch之22種損失函數數學公式和代碼定義 深度學習pytorch之19種優化算法&#xff08;optimizer&#xff09;解析 深度學習pytorch之4種歸一化方法&#xff08;Normalization&#xff09;原理公式解析和參數使用 深度學習pytorch之簡單方法自定義9類卷積即插即用 實時…

C++ Primer 拷貝控制和資源管理

歡迎閱讀我的 【CPrimer】專欄 專欄簡介&#xff1a;本專欄主要面向C初學者&#xff0c;解釋C的一些基本概念和基礎語言特性&#xff0c;涉及C標準庫的用法&#xff0c;面向對象特性&#xff0c;泛型特性高級用法。通過使用標準庫中定義的抽象設施&#xff0c;使你更加適應高級…

【無監督學習】層次聚類步驟及matlab實現

層次聚類 &#xff08;四&#xff09;層次聚類1.算法步驟2.MATLAB 實現參考資料 &#xff08;四&#xff09;層次聚類 層次聚類是一種通過逐層合并或分裂數據點構建樹狀結構&#xff08;樹狀圖&#xff0c;Dendrogram&#xff09;的聚類方法。它分為兩種類型&#xff1a; 凝聚…

02 HarmonyOS Next儀表盤案例詳解(一):基礎篇

溫馨提示&#xff1a;本篇博客的詳細代碼已發布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下載運行哦&#xff01; 文章目錄 1. 項目概述2. 技術架構2.1 文件結構2.2 ArkTS 語言特性裝飾器的使用 3. 數據結構設計3.1 接口定義3.2 數據初始化 4. 生命周期與頁面路由…

微信小程序接入deepseek

先上效果 話不多說&#xff0c;直接上代碼&#xff08;本人用的hbuilder Xuniapp&#xff09; <template><view class"container"><!-- 聊天內容區域 --><scroll-view class"chat-list" scroll-y :scroll-top"scrollTop":…

istio入門到精通-2

上部分講到了hosts[*] 匹配所有的微服務&#xff0c;這部分細化一下 在 Istio 的 VirtualService 配置中&#xff0c;hosts 字段用于指定該虛擬服務適用的 目標主機或域名。如果使用具體的域名&#xff08;如 example.com&#xff09;&#xff0c;則只有請求的主機 域名與 exa…

6. PromQL的metric name(在node exporter復制下來交給AI解釋的)

目錄 前言&#xff1a; Go 運行時指標&#xff1a; Go 內存統計指標&#xff1a; CPU 指標&#xff1a; 內存指標&#xff1a; 磁盤指標&#xff1a; 網絡指標&#xff1a; 系統指標&#xff1a; 前言&#xff1a; 寫這個得目的是為了后續方便查詢&#xff0c;因為在pro…

圖像形成與計算機視覺基礎

1. 圖像形成的基本原理 圖像形成是物理世界與傳感器&#xff08;如膠片、CCD/CMOS&#xff09;交互的過程&#xff0c;核心是光線的傳播與記錄。 1.1 直接放置膠片模型 物理原理&#xff1a;物體表面反射的光線直接照射到膠片上&#xff0c;但無任何遮擋或聚焦機制。 問題&a…

Dockerfile概述及編輯

文章目錄 Docker 鏡像原理操作系統組成部分Docker 鏡像原理鏡像制作 Dockerfile概念及作用Dockerfile 概念Dockerfile 作用 Dockerfile關鍵字 案例要求實現步驟 Docker 鏡像原理 操作系統組成部分 操作系統組成&#xff1a;進程調度子系統、進程通信子系統、內存管理子系統、…

CES Asia 2025:AR/VR/XR論壇峰會備受矚目

CES Asia 2025第七屆亞洲消費電子技術貿易展&#xff08;賽逸展&#xff09;將在首都北京心盛大舉行。作為亞洲極具影響力的消費電子技術展會&#xff0c;此次盛會以“科技重塑生活&#xff0c;創新定義未來”為主題&#xff0c;預計將吸引全球500展商、100,000專業觀眾參與&am…

【Java線程基礎操作詳解】

Java線程基礎操作詳解 前言1. 線程創建1.1 繼承Thread類1.2 實現Runnable接口1.3 匿名內部類1.4 lambda表達式 2. 線程中斷3. 線程等待4. 線程休眠 前言 在Java編程里&#xff0c;線程是實現多任務處理的關鍵概念。本文會詳細講解Java中線程的創建、中斷、等待以及休眠等操作&…

qt 播放pcm音頻

一、獲取PCM音頻 ffmpeg -i input.mp3 -acodec pcm_s16le -ar 44100 -ac 2 -f s16le output.pcm -acodec pcm_s16le&#xff1a;指定16位小端PCM編碼格式&#xff08;兼容性最佳&#xff09;-ar 44100&#xff1a;設置采樣率為CD標準44.1kHz&#xff08;可替換為16000/8000等&a…

python實現的可愛卸載動畫

在逛掘金時&#xff0c;掘金用戶在B站看到的靈感進行的一個卸載窗口的動畫效果的實用案例。人類是一種不斷在學習的動物&#xff0c;并且是一種模仿能力學習能里比較強的動物。我這里是第三波的學習實踐者咯&#xff01; 相對VUE構建動畫效果窗口&#xff0c;我更加喜歡用pytho…

出現FullGC的排查思路

一、明確Full GC的觸發原因 根據多篇資料&#xff0c;Full GC的觸發條件主要包括&#xff1a; 直接調用System.gc()&#xff1a;代碼或第三方庫&#xff08;如jxl組件&#xff09;可能顯式觸發。老年代空間不足&#xff1a;大對象直接進入老年代、Minor GC后存活對象過多導致…