中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

上線了做網站多少錢百度收錄排名

上線了做網站多少錢,百度收錄排名,天元建設集團有限公司 李增啟,html歐美網站模板工程 | JOSH LONG | 0條評論 Java 22發(fā)布快樂! Java 22 是一個重大的進步,是一個值得升級版本。有一些重大的最終發(fā)布功能,如 Project Panama及一系列更優(yōu)秀的預覽功能。我不可能覆蓋它們全部,但我確實想談談我最喜愛的一些。我們…

工程 | JOSH LONG | 0條評論

Java 22發(fā)布快樂!

Java 22 是一個重大的進步,是一個值得升級版本。有一些重大的最終發(fā)布功能,如 Project Panama及一系列更優(yōu)秀的預覽功能。我不可能覆蓋它們全部,但我確實想談談我最喜愛的一些。我們將會涉及到許多功能。如果你想在家里跟著做,代碼在這。

我愛Java 22,當然,我也愛 GraalVM,它們都在發(fā)布了新版本!Java 當然是我們最喜愛的運行時和語言,而 GraalVM 是一個高性能的 JDK 發(fā)行版,它支持更多語言并允許提前編譯(它們被稱為 GraalVM native images)。GraalVM 包含了 Java 22 新版的所有好東西,還有一些額外的工具,所以我總是推薦下載那個版本。我特別感興趣的是 GraalVM native image 的能力。生成的二進制文件幾乎可以立即啟動,并且與它們的 JRE 相比,消耗的 RAM 明顯少。GraalVM 不是新事物,但值得記住的是,Spring Boot 有一個很棒的引擎,支持將你的 Spring Boot 應用程序轉化為 GraalVM native images。

1 安裝

我正在使用一個出色的 Java 包管理器 SDKMAN。我還在運行帶有 macOS 的 Apple Silicon 芯片。所以,這個事實和我喜歡并鼓勵使用 GraalVM 的事實稍后會有些重要,所以不要忘了。將會有測試!

sdk install java 22-graalce

我還會設置它為你的默認選擇:

sdk default java 22-graalce

在繼續(xù)之前,打開一個新的 shell,然后通過運行 javac --versionjava --version,和 native-image --version 來驗證一切是否正常。

如果你是在遙遠的未來閱讀這篇文章的(我們已經有飛行汽車了嗎?)而且有 50-graalce,那么就盡情安裝那個版本!版本越新越好!

2 你總得從某處開始...

在這一點上,我想要開始構建了!所以,我去了互聯(lián)網上第二喜歡的地方,Spring Initializr - start.spring.io - 并生成了一個新的項目,使用以下規(guī)格:

  • 我選擇了 3.3.0-snapshot 版本的 Spring Boot。3.3 還沒有正式發(fā)行,但應該在短短幾個月內就會。與此同時,不斷前進!這個版本對 Java 22 有更好的支持。
  • 我選擇了 Maven 作為構建工具。
  • 我添加了 GraalVM Native Support 支持,H2 Database,和 JDBC API 支持。

我在我的 IDE 中打開了項目,像這樣:idea pom.xml。現(xiàn)在我需要配置一些 Maven 插件以支持 Java 22 和一些我們將在本文中看到的預覽功能。這是我的完整配置的 pom.xml。它有點密集,所以我會在代碼結束后來介紹一下。

COPY<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0-SNAPSHOT</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>22</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.graalvm.sdk</groupId><artifactId>graal-sdk</artifactId><version>23.1.2</version></dependency><dependency><groupId>org.graalvm.nativeimage</groupId><artifactId>svm</artifactId><version>23.1.2</version><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.10.1</version><configuration><buildArgs><buildArg> --features=com.example.demo.DemoFeature</buildArg><buildArg> --enable-native-access=ALL-UNNAMED </buildArg><buildArg> -H:+ForeignAPISupport</buildArg><buildArg> -H:+UnlockExperimentalVMOptions</buildArg><buildArg> --enable-preview</buildArg></buildArgs></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><argLine>--enable-preview</argLine></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><enablePreview>true</enablePreview></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><compilerArguments> --enable-preview </compilerArguments><jvmArguments> --enable-preview</jvmArguments></configuration></plugin><plugin><groupId>io.spring.javaformat</groupId><artifactId>spring-javaformat-maven-plugin</artifactId><version>0.0.41</version><executions><execution><phase>validate</phase><inherited>true</inherited><goals><goal>validate</goal></goals></execution></executions></plugin></plugins></build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></pository></repositories><pluginRepositories><pluginRepository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></pluginRepository><pluginRepository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></pluginRepository></pluginRepositories>
</project>

我知道,我知道!很多!但實際上并不是這樣。這個 pom.xml 幾乎和我從 Spring Initializr 獲取的一模一樣。主要改變:

  • 重新定義 maven-surefire-pluginmaven-compiler-plugin 支持預覽功能。
  • 添加 spring-javaformat-maven-plugin 用來支持格式化我的源代碼。
  • 添加兩個新依賴項:org.graalvm.sdk:graal-sdk:23.1.2org.graalvm.nativeimage:svm:23.1.2,都是專門為后面我們將需要的 GraalVM Feature 實現(xiàn)創(chuàng)建的
  • native-maven-pluginspring-boot-maven-plugin<configuration> 部分添加了配置節(jié)

非??炀偷搅?#xff0c;Spring Boot 3.3 將會正式發(fā)布并支持 Java 22,所以可能這個構建文件的一半會消失。(真是春天的清理!)

3 編程快速說明

LanguageDemonstrationRunner ,一個功能性接口,聲明可拋 Throwable。

package com.example.demo;@FunctionalInterface
interface LanguageDemonstrationRunner {void run() throws Throwable;}

我還有一個 ApplicationRunner,反過來,它注入了我所有的功能接口實現(xiàn),然后調用它們的 run 方法,捕獲并處理 Throwable。

    // ...    @BeanApplicationRunner demo(Map<String, LanguageDemonstrationRunner> demos) {return _ -> demos.forEach((_, demo) -> {try {demo.run();} //catch (Throwable e) {throw new RuntimeException(e);}});}// ...

好的,既然我們已經講過了,那就開始吧!

4 再見,JNI!

此版本終于等待了已久的 Project Panama 的發(fā)布。我最期待的三個特性之一,另外兩個特性是:

  • 虛擬線程
  • GraalVM native images

它們至少已經成為現(xiàn)實六個月了。Project Panama 是讓我們能夠利用長期以來被拒之門外的 C 和 C++ 代碼的星系?;叵肫饋?#xff0c;如果它支持 ELF,我想象。例如 Rust 和 Go 程序可以編譯成與 C 兼容的二進制文件,所以我想象(但沒有嘗試過)這意味著與這些語言的互操作也足夠容易。在本節(jié)中,當我提到“原生代碼”時,我指的是以某種方式編譯的二進制文件,它們可以像 C 庫那樣被調用。

從歷史上看,Java 一直是孤立的。對于 Java 開發(fā)人員來說,重新使用原生 C 和 C++ 代碼并不容易。這是有道理的。原生、特定于操作系統(tǒng)的代碼只會破壞 Java 的“一次編寫,到處運行”的承諾。它一直是有點禁忌的。但我不明白為什么會這樣。公平地說,盡管缺乏易用的原生代碼互操作功能,我們也做得不錯。幾乎任何你想要做的事情,可能都有一個純 Java 解決方案存在,它可以在 Java 運行的任何地方運行。它運行得很好,直到它不再運行。Java 在這里錯過了關鍵的機會。想象一下:

  • 如果 Kubernetes 是用 Java 構建的?
  • 如果當前的 AI 革命是由 Java 驅動的?

這兩個概念會不可思議,當 Numpy、Scipy 和 Kubernetes 最初創(chuàng)建時,但是今天?今天,他們發(fā)布了 Panama 項目。

Panama 項目引入了一種容易連接原生代碼的方法。支持兩個級別。你可以以相當?shù)图壍姆绞讲倏v內存,并將數(shù)據(jù)在原生代碼中來回傳遞。我說“來回”,但我可能應該說“向下和向上”到原生代碼。Panama 項目支持“向下調用”,即從 Java 調用原生代碼,以及“向上調用”,即從原生代碼調用 Java。你可以調用函數(shù)、分配和釋放內存、讀取和更新 struct 中的字段等等。

讓我們來看一個簡單的例子。代碼使用新的 java.lang.foreign.* API 查找一個叫做 printf 的符號(基本上就是 System.out.print()),分配內存(有點像 malloc)緩沖區(qū),然后將該緩沖區(qū)傳遞給 printf 函數(shù)。

package com.example.demo;import org.springframework.stereotype.Component;import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.SymbolLookup;
import java.util.Objects;import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_INT;@Component
class ManualFfi implements LanguageDemonstrationRunner {// 這是包私有的,因為我們稍后會需要它static final FunctionDescriptor PRINTF_FUNCTION_DESCRIPTOR =FunctionDescriptor.of(JAVA_INT, ADDRESS);private final SymbolLookup symbolLookup;// SymbolLookup 是 Panama API,但我有一個我正在注入的實現(xiàn)ManualFfi(SymbolLookup symbolLookup) {this.symbolLookup = symbolLookup;}@Overridepublic void run() throws Throwable {var symbolName = "printf";var nativeLinker = Linker.nativeLinker();var methodHandle = this.symbolLookup.find(symbolName).map(symbolSegment -> nativeLinker.downcallHandle(symbolSegment, PRINTF_FUNCTION_DESCRIPTOR)).orElse(null);try (var arena = Arena.ofConfined()) {var cString = arena.allocateFrom("hello, Panama!");Objects.requireNonNull(methodHandle).invoke(cString);}}}

這是我提出的 SymbolLookup 的定義。它是一種復合體,嘗試一個 SymbolLookup,如果第一個失敗,則嘗試另一個。

@Bean
SymbolLookup symbolLookup() {var loaderLookup = SymbolLookup.loaderLookup();var stdlibLookup = Linker.nativeLinker().defaultLookup();return name -> loaderLookup.find(name).or(() -> stdlibLookup.find(name));
}

運行這個,你會看到它打印出 hello, Panama!.

您可能想知道為什么我沒有選擇更有趣的例子。事實證明,在所有os中你既能理所當然地享有,在計算機上也能感知到自己做了些什么的東西幾乎沒有。IO 似乎是我能想到的所有東西,而且控制臺 IO 更容易理解。

但 GraalVM 原生鏡像咋樣呢?它并不支持你可能想做的每件事。至少目前,它不在蘋果芯片運行,只在 x86 芯片。我開發(fā)了這個例子,并設置了 GitHub 操作在 x86 Linux 環(huán)境中查看結果。對于我們這些不使用英特爾芯片的 Mac 開發(fā)者來說,這有點遺憾,但我們大多數(shù)人不是將產品部署到蘋果設備上,我們是部署到 Linux 和 x86 上,所以這不是一個破壞協(xié)議的事情。

還有一些其他限制。如GraalVM 原生映像僅支持我們復合中的第一個 SymbolLookup, loaderLookup。如果那個不起作用,那么它們都將不起作用。

GraalVM 想要知道你在運行時會做的一些動態(tài)事情,包括外部函數(shù)調用。你需要提前告訴它。對于其他需要此類信息的大多數(shù)事情,如反射、序列化、資源加載等,你需要編寫 .json 配置文件(或讓 Spring 的 AOT 引擎為你編寫)。這個特性是如此新,以至于你必須走下幾個抽象層次并編寫一個 GraalVM Feature 類。Feature 有回調方法,在 GraalVM 的本地編譯生命周期中被調用。你將告訴 GraalVM 我們最終會在運行時調用的原生函數(shù)的簽名,即形態(tài)。這是 Feature。只有一行價值。

package com.example.demo;import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeForeignAccess;import static com.example.demo.ManualFfi.PRINTF_FUNCTION_DESCRIPTOR;public class DemoFeature implements Feature {@Overridepublic void duringSetup(DuringSetupAccess access) {// 這是唯一重要的一行。注意:我們正在分享// 我們稍早從 ManualFfi bean 中的 PRINTF_FUNCTION_DESCRIPTOR。RuntimeForeignAccess.registerForDowncall(PRINTF_FUNCTION_DESCRIPTOR);}}

然后我們需要連接所有的特性,通過將 --features 屬性傳遞給 GraalVM 原生圖像 Maven 插件配置來告知 GraalVM。我們還需要解鎖外部 API 支持和解鎖實驗性事物。(我不知道為什么在 GraalVM 原生鏡像中這是實驗性的,而在 Java 22 本身中它不再是實驗性的)。還需要告訴 GraalVM 允許所有未命名類型的原生訪問。所以,總的來說,這是最終的 Maven 插件配置。

<plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.10.1</version><configuration><buildArgs><buildArg>--features=com.example.demo.DemoFeature</buildArg><buildArg>--enable-native-access=ALL-UNNAMED</buildArg><buildArg>-H:+ForeignAPISupport</buildArg><buildArg>-H:+UnlockExperimentalVMOptions</buildArg><buildArg>--enable-preview</buildArg></buildArgs></configuration>
</plugin>

這是一個了不起的結果。我將這個示例中的代碼編譯成一個在 GitHub Actions 運行中的 GraalVM 原生圖像然后執(zhí)行它。應用程式,我提醒您 - 具有 Spring JDBC 支持、完整和嵌入式 SQL 99 兼容的 Java 數(shù)據(jù)庫叫做 H2,以及類路徑上的所有內容 - 在 0.031 秒(31 毫秒,或 31 千分之一秒)內執(zhí)行,占用數(shù)十兆字節(jié)的 RAM,并從 GraalVM 原生鏡像調用原生 C 代碼!

我真的很高興,大家。我已經等這一天很久了。

但這確實感覺有點低級。歸根到底,你在使用一個 Java API 來以編程方式創(chuàng)建和維護原生代碼中的結構。這有點像使用 JDBC 中的 SQL。JDBC 允許你在 Java 中操縱 SQL 數(shù)據(jù)庫記錄,但你不是在 Java 中編寫 SQL 并在 Java 中編譯它并在 SQL 中執(zhí)行它。存在一個抽象增量;你將字符串發(fā)送到 SQL 引擎,然后以 ResultSet 對象的形式獲取回來的記錄。Panama 中的低級 API 也是如此。它起作用,但你沒有調用原生代碼,你正在查找符號和操縱內存。

所以,他們發(fā)布了一個與之分離但相關的工具叫做 jextract。你可以指向一個 C 頭文件,如 stdio.hprintf 函數(shù)定義在其中,它會生成模仿底層 C 代碼調用簽名的 Java 代碼。我沒有在這個示例中使用它,因為生成的 Java 代碼最終與底層平臺綁定。我指它去 stdio.h 并獲得了很多 macOS 特定的定義。我可以隱藏所有這些在運行時檢查操作系統(tǒng)的后面,然后動態(tài)加載特定的實現(xiàn),但是,嗯,這篇博客已經太長了。如果你想看怎么運行 jextract,這是我用的可以在 macOS 和 Linux 上工作的 bash 腳本。你的里程可能會有所不同。

#!/usr/bin/env bash
LINUX=https://download.java.net/java/early_access/jextract/22/3/openjdk-22-jextract+3-13_linux-x64_bin.tar.gz
MACOS=https://download.java.net/java/early_access/jextract/22/3/openjdk-22-jextract+3-13_macos-x64_bin.tar.gzOS=$(uname)DL=""
STDIO=""if [ "$OS" = "Darwin" ]; thenDL="$MACOS"STDIO=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h
elif [ "$OS" = "Linux" ]; thenDL=$LINUXSTDIO=/usr/include/stdio.h
elseecho "Are you running on Windows? This might work inside the Windows Subsystem for Linux, but I haven't tried it yet.."
fiLOCAL_TGZ=tmp/jextract.tgz
REMOTE_TGZ=$DL
JEXTRACT_HOME=jextract-22mkdir -p "$(dirname  $LOCAL_TGZ )"
wget -O $LOCAL_TGZ $REMOTE_TGZ
tar -zxf "$LOCAL_TGZ" -C .
export PATH=$PATH:$JEXTRACT_HOME/binjextract  --output src/main/java  -t com.example.stdio $STDIO

想想看,我們擁有簡單的外部函數(shù)互操作性、提供驚人擴展性的虛擬線程,以及靜態(tài)鏈接的、快如閃電、內存高效、自足的 GraalVM 原生圖像二進制文件。再次告訴我,為何你要開始一個新的 Go 項目?:-)

5 勇敢的新世界

Java 22 是一個驚人的新版本。它帶來了一系列巨大的功能和提升生活品質的改進。記住,不可能總是這樣美好!沒有人能每六個月就一貫地推出改變游戲規(guī)則的新功能。這是不可能的。所以,我們不妨心存感激,盡情享受目前吧,好嗎? :) 在我看來,上一個版本 Java 21,或許是我見過的自 Java 5 以來最重要的一次發(fā)布,甚至可能是最早。這可能是最大的一次!

那里有許多特性值得你關注,包括:

  • 數(shù)據(jù)導向編程
  • 虛擬線程

六月前為支持那次發(fā)布所做的博客中,覆蓋這些及更多內容,Hello, Java 21。

6 虛擬線程、結構化并發(fā)和作用域值

虛擬線程是真正重要的部分。閱讀我剛才鏈接給你的博客,往下翻。 (不要像 the Primeagen 那樣,他讀了文章但在還沒讀到最佳部分 - 虛擬線程之前就走神了!我的朋友……為什么??)

如果你正在運行 I/O 綁定的服務,虛擬線程是提高你的云基礎設施花費、硬件等的一個方法。它們使得你可以將現(xiàn)有的針對 java.io 中的阻塞 I/O API 編寫的代碼轉換為虛擬線程,并處理更好的規(guī)?;Mǔ5男Ч?#xff0c;你的系統(tǒng)不再不斷地等待線程的可用性,從而平均響應時間下降,更好的是,你會發(fā)現(xiàn)系統(tǒng)能夠同時處理更多的請求!我無法強調它的重要性。虛擬線程是棒極了!如果你在使用 Spring Boot 3.2,你只需要指定 spring.threads.virtual.enabled=true 即可享受它們!

虛擬線程是旨在使 Java 成為我們都知道它應該得到的精簡、高效的規(guī)?;瘷C器的一系列新功能的一部分,而且它正在起作用!虛擬線程是三個旨在協(xié)同工作的功能中的唯一一個已經在發(fā)布形式中交付的功能。

結構化并發(fā)和作用域值都還沒有落地。結構化并發(fā)為構建并發(fā)代碼提供了一個更優(yōu)雅的編程模型,而作用域值則提供了一個效率更高、更通用的 ThreadLocal<T> 替代方案,特別適用于虛擬線程的背景下,其中你現(xiàn)在可以實際擁有數(shù)百萬個線程。想象一下對于每一個這樣的線程都有重復的數(shù)據(jù)!

這些功能在 Java 22 中處于預覽階段。我不知道它們現(xiàn)在是否值得展示。在我心中,虛擬線程是魔法的一部分,它們之所以如此神奇,正是因為你真的不需要了解它們!只設置那一個屬性,你就可以啟動了。

虛擬線程為你提供了類似 Python、Rust、C#、TypeScript、JavaScript 的 async/await 或 Kotlin 中的 suspend 之類的驚人規(guī)模,而無需使用那些語言功能所需的固有冗長代碼和繁瑣工作。這是少數(shù)幾次,除了可能是 Go 的實現(xiàn),Java 在結果上是直接更勝一籌的時候。Go 的實現(xiàn)是理想的,但那只是因為他們在 1.0 版本中就內置了這一點。事實上,Java 的實現(xiàn)更為杰出,精確地說是因為它與較老的平臺線程模型共存。

7 隱式聲明的類和實例主方法

這個預覽功能是巨大的生活質量提升,盡管結果代碼更小,而我非常歡迎它。不幸的是,它目前還與 Spring Boot 不兼容?;靖拍钍?#xff0c;總有一天你將能夠只有一個頂層 main 方法,而不需要今天 Java 中的所有儀式。作為應用程序的入口點,這不是很好嗎?沒有 class 定義,沒有 public static void,沒有不必要的 String[] 參數(shù)。

void main() {System.out.println("Hello, world!");
}

8 超類之前的語句

這是一個不錯的生活質量功能?;旧?#xff0c;Java 不允許你在子類中調用 super 構造函數(shù)之前訪問 this。其目的是為了避免與無效狀態(tài)相關的一類錯誤。但這有點過于嚴厲,并迫使開發(fā)者在想要在調用 super 方法之前進行任何非平凡計算時,不得不轉而使用 private static 輔助方法。這是有時所需的體操動作的一個例子。我從 the JEP 頁面偷來了這個例子:

class Sub extends Super {Sub(Certificate certificate) {super(prepareByteArray(certificate));}// 輔助方法private static byte[] prepareByteArray(Certificate certificate) {var publicKey = certificate.getPublicKey();if (publicKey == null)throw new IllegalArgumentException("null certificate");return switch (publicKey) {case RSAKey rsaKey -> ///...case DSAPublicKey dsaKey -> ...//...default -> //...};}}

你可以看到問題。這個新的 JEP,目前還是預覽功能,將允許你將該方法直接內聯(lián)在構造函數(shù)本身,增強可讀性并消除代碼冗余。

9 未命名的變量和模式

未命名的變量和模式是另一個提升生活質量的功能。然而,它已經交付了。

當你在創(chuàng)建線程,或者使用 Java 8 的流和收集器時,你將創(chuàng)建很多 lambda。實際上,在 Spring 中有很多情況下你會使用 lambdas。只需考慮所有的 *Template 對象,及其以回調為中心的方法。 JdbcClientRowMapper<T> 也跳入腦海!

有趣的事實:Lambda 首次在 2014 年的 Java 8 版本中介紹。 (是的,已經過去了一個十年!那時人們在做冰桶挑戰(zhàn),世界癡迷于自拍棒、FrozenFlappy Bird。),但它們的驚人品質是幾乎前 20 年的 Java 代碼在一夜之間如果方法期望單個方法接口實現(xiàn)就可以參與 lambdas。

Lambdas 是驚人的。它們在 Java 語言中引入了一個新的重用單元。最棒的部分是它們被設計為以某種方式嫁接到運行時的現(xiàn)有規(guī)則上,包括自動將所謂的功能接口或 SAMs(單抽象方法)接口適應到 lambdas。我唯一的抱怨是,屬于包含作用域的 lambda 中引用的東西必須設置為 final。這個問題已經修復。現(xiàn)在必須拼出每個 lambda 參數(shù),即使我根本沒打算使用它,現(xiàn)在,有了 Java 22,那也得到修復了!這里是一個冗長的例子,僅為了展示兩處 _ 字符的使用。因為我可以。

package com.example.demo;import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Component;import javax.sql.DataSource;@Component
class AnonymousLambdaParameters implements LanguageDemonstrationRunner {private final JdbcClient db;AnonymousLambdaParameters(DataSource db) {this.db = JdbcClient.create(db);}record Customer(Integer id, String name) {}@Overridepublic void run() throws Throwable {var allCustomers = this.db.sql("select * from customer ")// 這里! .query((rs, _) -> new Customer(rs.getInt("id"), rs.getString("name"))).list();System.out.println("all: " + allCustomers);}}

該類使用 Spring 的 JdbcClient 查詢底層數(shù)據(jù)庫。它一頁一頁地翻閱結果,然后涉及我們的 lambda,它符合 RowMapper<Customer> 類型,以幫助我們將結果適應到與我的領域模型一致的記錄。 RowMapper<T> 接口,我們的 lambda 符合它,有一個方法 T mapRow(ResultSet rs, int rowNum) throws SQLException,期望兩個參數(shù):我將需要的 ResultSet,以及我?guī)缀醪恍枰?rowNum?,F(xiàn)在,多虧 Java 22,我不需要指定它。就像在 Kotlin 或 TypeScript 中一樣,只需插入 _ 即可。不錯!

10 聚集者

Gatherers 是另一個在預覽中也很好的功能。 Viktor Klang,他在 Akka 上的了不起工作以及他在 Lightbend 期間對 Scala futures 的貢獻。如今,他是 Oracle 的一名 Java 語言架構師,他一直在研究的就是新的 Gatherer API。順便說一下,Stream API 也是在 Java 8 中引入的,這 - 順便說一下 - 給了 Java 開發(fā)者一個機會,與 lambdas 一起,大大簡化和現(xiàn)代化他們現(xiàn)有的代碼,并向更多函數(shù)式編程方向發(fā)展。

它構建了一個在值的流上進行一系列轉換的模型。然而,這個抽象模型并不盡完美。Streams API 提供了大量便利的方法,這些方法能夠滿足 99% 的使用場景,但當你遇到找不到合適方法的情況時,通常會感到挫敗,因為之前并沒有一種簡易的方式可以直接擴展新的操作。在過去十年間,關于為 Streams API 引入新操作的提案數(shù)不勝數(shù),甚至在最初的 lambda 表達式提案中,也有討論和妥協(xié),目的是讓編程模型有足夠的靈活性來支持新操作的加入?,F(xiàn)在,這一目標作為一個預覽性質的功能終于實現(xiàn)了。Gatherers 提供了一個稍微更底層的抽象層次,使你能夠在不需要將 Stream 具體化為 Collection 的情況下,在 Streams 上引入多種新操作。以下是一個我毫不掩飾地直接從 Viktor 和他的團隊那里取得的示例。

package com.example.demo;import org.springframework.stereotype.Component;import java.util.Locale;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Gatherer;
import java.util.stream.Stream;@Component
class Gatherers implements LanguageDemonstrationRunner {private static <T, R> Gatherer<T, ?, R> scan(Supplier<R> initial,BiFunction<? super R, ? super T, ? extends R> scanner) {class State {R current = initial.get();}return Gatherer.<T, State, R>ofSequential(State::new,Gatherer.Integrator.ofGreedy((state, element, downstream) -> {state.current = scanner.apply(state.current, element);return downstream.push(state.current);}));}@Overridepublic void run() {var listOfNumberStrings = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).gather(scan(() -> "", (string, number) -> string + number).andThen(java.util.stream.Gatherers.mapConcurrent(10, s -> s.toUpperCase(Locale.ROOT)))).toList();System.out.println(listOfNumberStrings);}}

該段代碼的重點在于,這里描述了一個名為 scan 的方法,它返回一個 Gatherer<T,?,R> 類型的實現(xiàn)。每個 Gatherer<T,O,R> 對象都需要一個初始化函數(shù)和一個整合函數(shù)。雖然這種實現(xiàn)自帶默認的合并函數(shù)和完成函數(shù),但你也可以自行覆蓋它們。它通過讀取所有的數(shù)字條目,并為每一個條目逐步構造一個字符串,字符串隨著數(shù)字的增加不斷累積。結果就像這樣:先是 1,然后是 12,接著是 123,直到 1234 等等。 上述例子還展示了 gatherers 是可以組合使用的。在這里,我們實際上操作了兩個 Gatherer 對象:一個用于執(zhí)行掃描過程,另一個則把每個元素轉成大寫,并且這一轉換是并發(fā)進行的。 如果您還沒能完全理解,沒關系,對于大多數(shù)人而言,這部分內容可能會有些深奧。大多數(shù)人可能無需自己編寫 Gatherers。但是,如果你想挑戰(zhàn)一下,也是可以試試的。我的朋友 Gunnar Morling 就在前幾天完成了這樣的工作。Gatherers 方法的巧妙之處在于,它使社區(qū)能夠根據(jù)自己的需求去設計解決方案。我很好奇這對于 Eclipse Collections、Apache Commons Collections 或者 Guava 這樣的著名項目會帶來什么影響?它們是否會推出 Gatherers?還有其他什么項目會加入這一趨勢?我期待看到很多實用的 gatherers 能夠聚集到同一個地方。

11 Class Parsing API

又一個令人期待的預覽性特性,這是 JDK 新增的部分,非常適合框架和基礎架構開發(fā)人員。它可以解答例如如何構建 .class 文件和如何讀取 .class 文件的問題。目前市場上有很多好用但不兼容,總是稍微有點落后的工具,比如 ASM(這個領域里的重量級解決方案),ByteBuddy,CGLIB 等。JDK 本身在其代碼庫中就包含了三種此類解決方案!這類庫在整個行業(yè)中隨處可見,并且對于像 Spring 這樣的框架的開發(fā)來說至關重要,Spring 動態(tài)地在運行時創(chuàng)建類來支持業(yè)務邏輯。你可以將它看作是一個反射 API,但它作用于 .class 文件——硬盤上實際的字節(jié)碼,而不是加載進 JVM 的對象。 這是一個簡單的例子,展示了如何把一個 .class 文件加載進一個 byte[] 數(shù)組,并對其進行分析。

package com.example.demo;import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;import java.lang.classfile.ClassFile;
import java.lang.classfile.FieldModel;
import java.lang.classfile.MethodModel;@Component
@ImportRuntimeHints(ClassParsing.Hints.class)
class ClassParsing implements LanguageDemonstrationRunner {static class Hints implements RuntimeHintsRegistrar {@Overridepublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {hints.resources().registerResource(DEFAULT_CUSTOMER_SERVICE_CLASS);}}private final byte[] classFileBytes;private static final Resource DEFAULT_CUSTOMER_SERVICE_CLASS = new ClassPathResource("/simpleclassfile/DefaultCustomerService.class");ClassParsing() throws Exception {this.classFileBytes = DEFAULT_CUSTOMER_SERVICE_CLASS.getContentAsByteArray();}@Overridepublic void run() {// this is the important logicvar classModel = ClassFile.of().parse(this.classFileBytes);for (var classElement : classModel) {switch (classElement) {case MethodModel mm -> System.out.printf("Method %s%n", mm.methodName().stringValue());case FieldModel fm -> System.out.printf("Field %s%n", fm.fieldName().stringValue());default -> {// ... }}}}}

這個例子稍微復雜一些,因為它涉及到了運行時讀取資源。為了應對這個過程,我實現(xiàn)了一個名為 Spring AOT RuntimeHintsRegistrar 的組件,它能生成一個 .json 文件。這個 JSON 文件記錄著我正在讀取的資源信息,比如具體來說就是 DefaultCustomerService.class 文件的數(shù)據(jù)。不過,這些都是幕后的技術細節(jié),主要是為了在 GraalVM 上進行本地鏡像編譯的時候使用。 而代碼底部的部分則頗有意思,我們對 ClassElement 實例進行了枚舉,并通過模式匹配的方法一一提取了各個要素。這真是太棒了!

12 String Templates

又一項預覽特性的加入,String templates 為 Java 帶來了字符串插值功能!Java 中的多行字符串(String)已經使用了一段時間。這個新功能允許開發(fā)者將編譯后字符串中可見的變量直接嵌入到字符串值里面。最精彩的部分?從理論上講,這個機制還可以自定義!不滿意現(xiàn)有的語法?你完全可以創(chuàng)造一個屬于你自己的版本。

package com.example.demo;import org.springframework.stereotype.Component;@Component
class StringTemplates implements LanguageDemonstrationRunner {@Overridepublic void run() throws Throwable {var name = "josh";System.out.println(STR.""" name: \{name.toUpperCase()}""");}}

13 總結

作為一名 Java 和 Spring 開發(fā)者,現(xiàn)在是一個前所未有的好時機!我一直強調這一點。我們仿佛獲得了一個嶄新的語言和運行時環(huán)境,這一進步 - 奇妙地 - 保持了對歷史版本的兼容。這是我目睹 Java 社區(qū)所開展的最具雄心壯志的軟件項目之一,我們很幸運能夠見證其成果的誕生。從現(xiàn)在起,我打算將 Java 22 和支持 Java 22 的 GraalVM 用于我的所有開發(fā)工作,我希望您也能跟我一起 關注我,緊跟本系列專欄文章,咱們下篇再續(xù)!

作者簡介:魔都技術專家兼架構,多家大廠后端一線研發(fā)經驗,各大技術社區(qū)頭部專家博主。具有豐富的引領團隊經驗,深厚業(yè)務架構和解決方案的積累。

負責:

  • 中央/分銷預訂系統(tǒng)性能優(yōu)化

  • 活動&優(yōu)惠券等營銷中臺建設

  • 交易平臺及數(shù)據(jù)中臺等架構和開發(fā)設計

  • 車聯(lián)網核心平臺-物聯(lián)網連接平臺、大數(shù)據(jù)平臺架構設計及優(yōu)化

    目前主攻降低軟件復雜性設計、構建高可用系統(tǒng)方向。

參考:

  • 編程嚴選網

本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!

http://www.risenshineclean.com/news/6543.html

相關文章:

  • 阿里云建網站流程谷歌seo優(yōu)化公司
  • 做動漫的游戲 迅雷下載網站專業(yè)seo站長工具
  • 做外貿英文網站哪家好深圳剛剛突然宣布
  • 域名訪問網站應該怎么做如何創(chuàng)建網站平臺
  • 衡水網站公司市場調研報告范文
  • 深圳外包網站制作公司網站搜索引擎
  • 網站推廣模式網站開發(fā)的流程
  • 國內做的好看的網站設計杭州seo網絡推廣
  • lamp網站架構民宿平臺搜索量上漲
  • 那個網站可以做全景圖網站的推廣方法有哪些
  • wordpress中修改鏈接地址東莞seo優(yōu)化推廣
  • 廣州模板建站定制網站提高銷售的10種方法
  • 網站商城的建設今天今日頭條新聞
  • 網站宣傳單舉出最新的網絡營銷的案例
  • 家居網站頁面設計圖片杭州百度快照優(yōu)化公司
  • 公司網站備案 問我借身份證 怎么拒絕百度網址入口
  • 網絡工程技術主要學什么網站優(yōu)化培訓班
  • 免費企業(yè)網站建設哪個網站案例
  • wordpress調用昵稱武漢網站seo服務
  • 七星彩投注網站建設最近三天的新聞大事摘抄
  • 怎么用ps做網站首頁圖片尺寸seo中心
  • 做企業(yè)網站需要人維護么seo運營做什么
  • 公司的做網站怎么優(yōu)化整站
  • 加強公司網站建設及數(shù)據(jù)庫的通知購物網站如何推廣
  • 業(yè)務員自己做網站新網絡營銷
  • wordpress調用指定id目錄青島網站優(yōu)化
  • 廣東高端建設網站金戈枸櫞酸西地那非片
  • 安卓市場網站建設廣告軟文范例大全100字
  • 微軟雅黑適合于做網站嗎競價托管開戶
  • b2b電子商務網站的主要類型有哪些如何做百度競價推廣