JDK 9 模塊化系統 (Module System) 和 多版本兼容 Jar (Multi-Release Jar)

博文目錄

文章目錄

  • Module System
    • 原因
    • JDK 模塊化
    • 模塊描述文件
      • 關鍵字
    • 啟用模塊化
    • 測試
    • 結論
  • Multi-Release jar (MRJAR)
    • 原因
    • 原理
    • 結論
    • 用 IDEA 創建多版本兼容 Jar
      • 項目結構
      • pom.xml
      • 測試


Module System

原因

Java 9引入了模塊化系統的主要原因是為了解決Java平臺面臨的復雜性和可維護性方面的挑戰。以下是一些采用模塊化系統的主要原因:

  • 更好的代碼組織:傳統的Java應用程序通常由大量的JAR文件組成,這些JAR文件之間的依賴關系可能變得非常復雜。模塊化系統允許開發人員將代碼組織為模塊,將相關的類和資源放在一起,使代碼更易于理解和維護。模塊化還提供了更細粒度的可見性和封裝,使開發人員能夠更好地控制代碼的可訪問性。
  • 更好的可重用性:模塊化系統鼓勵開發人員將功能劃分為獨立的模塊,這些模塊可以在不同的項目中重復使用。通過明確聲明模塊之間的依賴關系,模塊化系統提供了更好的可重用性和解耦性。
  • 更好的性能和安全性:模塊化系統允許JVM在運行時僅加載所需的模塊,而不是加載整個類路徑上的所有類。這可以提高應用程序的啟動時間和內存利用率。此外,模塊化系統通過明確聲明模塊之間的依賴關系,可以提供更好的安全性,防止不受信任的代碼訪問和修改模塊之間的內部實現。
  • 改進的可擴展性:模塊化系統引入了明確的導出和使用規范,使開發人員能夠更好地定義模塊之間的接口和依賴關系。這使得應用程序的功能可以更容易地進行擴展和定制,同時保持模塊之間的清晰界限。

總的來說,Java 9的模塊化系統提供了一種更好的方式來組織、重用和管理Java代碼,改善了傳統的類路徑模型面臨的復雜性和可維護性問題。它提供了更好的可見性、封裝性、性能、安全性和可擴展性,從而改進了Java開發的體驗和應用程序的質量。

JDK 模塊化

自 Java 9 起, JDK 自身也被模塊化, 按照功能劃分為一系列有依賴關系的模塊

  • java.base: 核心模塊, 最基礎模塊, 其他模塊都會依賴到它. 包含基本類庫和運行時環境, 如 Object, String, 集合框架, 輸入輸出, 并發工機具等, 是構建 Java 應用程序的基礎
  • java.se: 這個模塊表示 Java 標準版 (Java SE). 它是一個聚合模塊 (只有模塊描述文件 module-info.java), 其中引入了許多常用的模塊, 包含了大部分 Java SE 規范中定義的 API. 就相當于以前的 rt.jar
# 查看模塊列表
java --list-modules
# 查看模塊信息 (module-info.java)
java -d <模塊名稱>
java --describ-module <模塊名稱>

以下是 JDK 11.0.20 的模塊列表

> java --list-modules
java.base@11.0.20
java.compiler@11.0.20
java.datatransfer@11.0.20
java.desktop@11.0.20
java.instrument@11.0.20
java.logging@11.0.20
java.management@11.0.20
java.management.rmi@11.0.20
java.naming@11.0.20
java.net.http@11.0.20
java.prefs@11.0.20
java.rmi@11.0.20
java.scripting@11.0.20
java.se@11.0.20
java.security.jgss@11.0.20
java.security.sasl@11.0.20
java.smartcardio@11.0.20
java.sql@11.0.20
java.sql.rowset@11.0.20
java.transaction.xa@11.0.20
java.xml@11.0.20
java.xml.crypto@11.0.20
jdk.accessibility@11.0.20
jdk.attach@11.0.20
jdk.charsets@11.0.20
jdk.compiler@11.0.20
jdk.crypto.cryptoki@11.0.20
jdk.crypto.ec@11.0.20
jdk.crypto.mscapi@11.0.20
jdk.dynalink@11.0.20
jdk.editpad@11.0.20
jdk.hotspot.agent@11.0.20
jdk.httpserver@11.0.20
jdk.internal.ed@11.0.20
jdk.internal.jvmstat@11.0.20
jdk.internal.le@11.0.20
jdk.internal.opt@11.0.20
jdk.internal.vm.ci@11.0.20
jdk.internal.vm.compiler@11.0.20
jdk.internal.vm.compiler.management@11.0.20
jdk.jartool@11.0.20
jdk.javadoc@11.0.20
jdk.jcmd@11.0.20
jdk.jconsole@11.0.20
jdk.jdeps@11.0.20
jdk.jdi@11.0.20
jdk.jdwp.agent@11.0.20
jdk.jfr@11.0.20
jdk.jlink@11.0.20
jdk.jshell@11.0.20
jdk.jsobject@11.0.20
jdk.jstatd@11.0.20
jdk.localedata@11.0.20
jdk.management@11.0.20
jdk.management.agent@11.0.20
jdk.management.jfr@11.0.20
jdk.naming.dns@11.0.20
jdk.naming.ldap@11.0.20
jdk.naming.rmi@11.0.20
jdk.net@11.0.20
jdk.pack@11.0.20
jdk.rmic@11.0.20
jdk.scripting.nashorn@11.0.20
jdk.scripting.nashorn.shell@11.0.20
jdk.sctp@11.0.20
jdk.security.auth@11.0.20
jdk.security.jgss@11.0.20
jdk.unsupported@11.0.20
jdk.unsupported.desktop@11.0.20
jdk.xml.dom@11.0.20
jdk.zipfs@11.0.20

以下是 JDK 11.0.20 中, 聚合模塊 java.se 的模塊描述信息, 里面全是可傳遞的 requires

> java -d java.se
java.se@11.0.20
requires java.rmi transitive
requires java.management.rmi transitive
requires java.base mandated
requires java.instrument transitive
requires java.desktop transitive
requires java.transaction.xa transitive
requires java.security.jgss transitive
requires java.management transitive
requires java.prefs transitive
requires java.security.sasl transitive
requires java.xml transitive
requires java.sql transitive
requires java.naming transitive
requires java.datatransfer transitive
requires java.xml.crypto transitive
requires java.logging transitive
requires java.compiler transitive
requires java.scripting transitive
requires java.sql.rowset transitive
requires java.net.http transitive

模塊描述文件

模塊描述文件(module-info.java)是 Java 模塊化系統中的一個特殊文件,用于定義和配置模塊的屬性,依賴關系和訪問控制

  • 文件位置:模塊描述文件位于模塊的根目錄下(源碼目錄下,Maven 項目的源碼文件夾通常是 src/main/java 中的 java 文件夾),并以 module-info.java 作為文件名
  • 文件格式:模塊描述文件是一個普通的 Java 源代碼文件,使用 Java 編程語言的語法和結構進行編寫
  • 模塊聲明:模塊描述文件以 module 關鍵字開頭, 后跟模塊的名稱. 例如 module com.example.moduleName {}

關鍵字

  • module:在模塊描述文件(module-info.java)中,使用 “module” 關鍵字定義一個Java模塊。模塊是一組相關的類和資源的集合,具有明確的依賴關系和訪問控制
  • requires:使用 “requires” 關鍵字在模塊描述文件中聲明一個模塊依賴于其他模塊。例如,模塊 A 可以聲明 “requires B;”,表示模塊 A 依賴于模塊 B。
    • transitive:當一個模塊(例如模塊A)依賴于另一個模塊(例如模塊B)時,可以在 “requires” 語句中使用 “transitive” 關鍵字。例如,模塊 A 可以聲明 “requires B transitive;”,這意味著除了模塊 A 直接依賴于模塊 B 之外,任何依賴于模塊 A 的模塊也將隱式地依賴于模塊 B。這樣的傳遞性依賴關系可以簡化模塊之間的依賴管理。
  • exports:使用 “exports” 關鍵字在模塊描述文件中聲明一個模塊的包對其他模塊可見。通過 “exports” 語句,可以將模塊的公共 API 公開給其他模塊使用。例如,模塊 A 可以聲明 “exports com.example.package;”,表示模塊 A 將其名為 com.example.package 的包對其他模塊可見。
  • opens:與 “exports” 類似,“opens” 關鍵字也用于在模塊描述文件中聲明一個模塊的包對其他模塊可見。然而,與 “exports” 不同的是,“opens” 關鍵字還允許其他模塊通過反射訪問該包中的非公共類型。例如,模塊 A 可以聲明 “opens com.example.package;”,這樣其他模塊可以通過反射訪問 com.example.package 包中的非公共類型。需要與 “exports” 一起使用, 兩者合起來才是完整的權限
  • uses:使用 “uses” 關鍵字在模塊描述文件中聲明一個模塊使用某個服務接口。這表示該模塊需要在運行時從其他模塊中獲取實現該服務接口的提供者。例如,模塊 A 可以聲明 “uses com.example.ServiceInterface;”,表示模塊 A 需要使用 com.example.ServiceInterface 這個服務接口。
  • provides:使用 “provides” 關鍵字在模塊描述文件中聲明一個模塊提供某個服務接口的實現。這表示該模塊是服務接口的一個提供者。例如,模塊 A 可以聲明 “provides com.example.ServiceInterface with com.example.ServiceImpl;”,表示模塊 A 提供了com.example.ServiceInterface 接口的實現 com.example.ServiceImpl。
  • to:與 “provides” 關鍵字一起使用,指定一個或多個使用該服務接口的模塊。例如,模塊 A 可以聲明 “provides com.example.ServiceInterface with com.example.ServiceImpl to moduleB, moduleC;”,表示模塊 A 提供的 com.example.ServiceInterface實現將供模塊 B 和模塊 C 使用。

啟用模塊化

  • JDK 9 及以上
  • 添加模塊描述文件 module-info.java

測試

生成一個模塊化項目, 做一個工具類, 打包安裝到 Maven 本地倉庫, 用另一個普通項目依賴該 Jar 做測試, 將普通項目改成模塊化項目做測試

結論

  • 非模塊化項目可以依賴模塊化的 Jar
  • 模塊化的項目依賴非模塊化的 Jar 則比較麻煩
    • 需要手動修改 Jar 的 MANIFEST.MF, 通過 Automatic-Module-Name 屬性指定模塊名(文件名), 將普通 Jar 修改為隱式模塊, 然后通過 requires 引用
  • 由于很多第三方 Jar 都沒有做模塊化適配, 且模塊化的項目依賴其他普通 Jar 的時候會比較麻煩, 所以暫不推薦搭建模塊化項目, 這樣就可以直接使用非模塊化 Jar 和模塊化 Jar
    • 如果依賴的第三方 Jar 都是模塊化的, 那還是推薦把項目改成模塊化項目, 可戰未來

Multi-Release jar (MRJAR)

JEP 238: Multi-Release JAR Files

原因

Creating Multi-Release JAR Files in IntelliJ IDEA

在過去,庫開發人員在支持較新版本的 Java 時有三種選擇:

  • 提供兩個(或更多!)不同的JAR文件,每個JAR文件對應于他們想要支持的Java版本。這些可能帶有版本號,如“1.2-java-5”和“1.2-java-1.3”。
  • 將您的每一個版本都綁定到特定版本的Java,迫使用戶要么升級他們的Java版本,要么停留在舊版本的庫中。例如,“5.0版以后的版本需要Java 8”。
  • 堅持為用戶發布最低公分母版本。對于許多庫開發人員來說,這意味著他們仍然是根據Java 6進行編譯的,并且在幾乎所有用戶都已經遷移到Java 8之前,不能遷移到使用Java 8的功能,如lambdas和流。
    • "最低公分母版本"是指在開發和發布軟件時所考慮的目標用戶群體中所使用的最舊版本的共同特性或功能子集。這意味著開發人員會選擇支持最舊的、被廣泛采用的版本,以確保盡可能多的用戶能夠使用他們的軟件。

對于庫開發人員或用戶來說,這些方法都不是特別有趣。它們要么涉及大量工作,要么疏遠/混淆用戶,要么庫無法利用新功能(因此也沒有給用戶提供太多升級Java版本的動力)。

從Java 9開始,還有一種選擇。現在,庫開發人員可以發布一個JAR文件,該文件:

  • 如果您在Java 9上運行它,會使用Java 9的特性和功能
  • 如果您在Java 9之前的版本上運行它,那么您將使用Java 9之前版本的實現。

這適用于Java 9以后的版本——因此這些多版本JAR文件將支持Java 9版本、Java 10(或18.3)、11、12版本等……但Java 9之前的任何內容都被歸為“Java 9之前”。這有點令人難過,因為顯然Java 8有一些不錯的功能,如果你運行Java 8,你可能會想要這些功能,但Java 9之前對庫的支持可能會像許多庫一樣,以Java6為目標,Java 8本身無法決定在運行多版本JAR文件時要做什么,因為該功能僅在Java 9中可用。

原理

root- A.class- B.class- C.class- D.class- META-INF- MANIFEST.MF- versions- 9- A.class- B.class- 11- B.class

基本上,您有一個標準的JAR文件,像往常一樣,在根目錄中包含應用程序中的所有類,在META-INF中還有一個額外的 “versions” 文件夾,其中包含每個額外支持的Java版本的特定實現(在本例中,只有Java 9)。這個“9”文件夾只需要包含那些具有特定Java 9功能的類的類文件。如果不存在類(例如C.class),則將使用默認版本。

翻譯成人話就是說, Java 9 在現有 Jar 結構的基礎上擴展了 versions 機制, 如果使用 Java 6/7/8, 會使用到 root 下的 A/B/C/D 類, 如果使用 Java 9, 則會使用到 root/META-INF/versions/9 下的 A/B 類和 root 下的 C/D 類, 如果使用 Java 10, 和 Java 9 的情況一樣, 如果使用 Java 11, 則會使用到 root/META-INF/versions/11 下的 B 類, root/META-INF/versions/9 下的 A 類, 還有 root 下的 C/D 類

只要將 Jar 包各部分用指定的 JDK 編譯, 然后按照上述規范打包, 在 MANIFEST.MF 中額外指定 Multi-Release: true, 那么這個 Jar 就是一個多版本兼容 Jar 了, 在不同的 Java 環境下, 會自動選擇合適版本的類. 這里有一個隱藏規范, 就是多個版本的類的 API 需要完全一致, 這個不是必須, 但是建議一致, 不然在使用中可能會出問題

結論

是一種好方法, 推薦開發庫時使用

Java多版本兼容JAR的好處主要有以下幾點:

  • 平滑遷移:Java多版本兼容JAR使得開發人員在升級Java版本時能夠平滑遷移他們的應用程序。通過使用兼容的JAR文件,可以確保應用程序在不同版本的Java運行時環境中都能正常運行,而無需對現有的代碼進行重寫或修改。
  • 擴展用戶基礎:通過使用多版本兼容JAR,開發人員可以支持廣泛的用戶群體,包括那些仍在使用較舊Java版本的用戶。這使得應用程序能夠覆蓋更多的用戶,并且不會因為某些用戶無法升級到最新Java版本而失去潛在的用戶和市場份額。
  • 提高可靠性和穩定性:多版本兼容JAR可以提高應用程序的可靠性和穩定性。通過確保應用程序在不同Java版本上的兼容性,可以降低因為Java版本升級而引入的潛在兼容性問題和錯誤。
  • 簡化部署和維護:Java多版本兼容JAR使得應用程序的部署和維護更加簡化。開發人員只需提供一個通用的JAR文件,而不需要為每個Java版本提供單獨的構建或分發。這簡化了應用程序的構建、部署和維護流程,并減少了潛在的錯誤和混亂。
  • 充分利用新功能:多版本兼容JAR使得開發人員能夠利用每個Java版本引入的新功能和改進。通過將新功能包裝在兼容的JAR中,開發人員可以將這些功能提供給那些使用較新Java版本的用戶,而無需犧牲對較舊Java版本的兼容性。

總的來說,Java多版本兼容JAR提供了一種靈活和可靠的方式,使得Java應用程序能夠在各種不同版本的Java運行時環境中運行,并且能夠充分利用每個版本的新功能。這為開發人員提供了更大的靈活性、更廣泛的用戶覆蓋范圍和更簡化的部署維護流程。

用 IDEA 創建多版本兼容 Jar

Creating Multi-Release JAR Files in IntelliJ IDEA
Java SE 9 多版本兼容 JAR 包示例, 兩個例子應該都沒有使用 IDEA, 可以參考

Maven 支持在一個模塊中創建兩個源碼文件夾, 并設置編輯級別, 以此來編譯并打包, 但是在 IDEA 中, 同一個模塊只能設置一個編輯級別, 且兩個源碼文件夾中不允許有完全相同的包和類. 用 IDEA 構建 Multi-Release Jar 需要忍受幾個點, 一是不能按照源碼文件夾設置語言級別(開發時無對應語言級別檢查), 二是兩個完全相同的類會報重復錯誤(不能直接運行測試). 其他的使用 IDEA 的 Maven 插件就可以搞定了

項目結構

新建一個 Maven 項目, JDK 選一個高版本的, 這里是 21.0.1, 項目結構如下, java 源碼包用 8 編譯, java.11 源碼包用 11 編譯, 工具類里可以針對不同編譯級別使用不同 API, 如 Paths.get 與 Path.of, 還有 Files.readString 等, 查看 @since

在這里插入圖片描述

pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.coder</groupId><artifactId>demo.multi.release.jar</artifactId><version>1.0.0</version><properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.11.0</version><executions><execution><!--覆蓋默認階段和目標綁定的配置--><id>default-compile</id><goals><goal>compile</goal></goals><configuration><!--從 JDK 9 起, 使用 release 替代 source 和 target, 因為后者不能保證代碼在使用指定版本的JDK編譯, 具體可參考下面兩個鏈接--><!-- https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-release.html --><!-- https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html --><release>8</release><compileSourceRoots><compileSourceRoot>${project.basedir}/src/main/java</compileSourceRoot></compileSourceRoots></configuration></execution><execution><id>compile-java-11</id><phase>compile</phase><goals><goal>compile</goal></goals><configuration><release>11</release><compileSourceRoots><compileSourceRoot>${project.basedir}/src/main/java.11</compileSourceRoot></compileSourceRoots><outputDirectory>${project.build.outputDirectory}/META-INF/versions/11</outputDirectory></configuration></execution><execution><!--覆蓋默認階段和目標綁定的配置--><id>default-testCompile</id><phase>test-compile</phase><goals><goal>testCompile</goal></goals><configuration><skip>true</skip></configuration></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.3.0</version><configuration><archive><manifestEntries><Multi-Release>true</Multi-Release></manifestEntries></archive></configuration></plugin></plugins></build></project>

測試

新建一個 java maven 項目, 依賴該多版本兼容 Jar, 分別設置項目 SDK 版本為 8/9/11/21 等, 查看輸出內容, 查看 class 文件內容

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

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

相關文章

線程的使用(二)

新增實現方式之實現Callable接口 特點 1、可以有返回值。 2、方法可以拋異常。 3、支持泛型的返回值。 4、需借助FutureTask類&#xff0c;比如獲取返回值。 步驟 1、創建一個實現Callable接口的實現類。 2、重寫call方法&#xff0c; 將此線程需執行的操作聲明在call&…

C++中STL的容器vector

文章目錄 什么是vectorvector與普通順序表不同的點 vector的成員函數operatoroperator[]begin與end與iteratorsize()capacityresizeemptyreservepush_backpop_backinserteraseswapclear成員變量 總結 什么是vector vector&#xff1a;是數據結構里面的順序表&#xff0c;開辟一…

【LeetCode刷題】數組篇2

&#x1f387;數組中等題Part &#x1f308; 開啟LeetCode刷題之旅 &#x1f308; 文章目錄 &#x1f387;數組中等題Part&#x1f370;229.多數元素II&#x1f451;思路分析1.哈希表法2.摩爾投票法(進階) &#x1f370;15.三數之和&#x1f451;思路分析1.排序雙指針 &#x…

ES6拓展API

1.對象API拓展 is 判斷兩個值是否相等 is(0,-0);false is(NaN,NaN) true (NaN NaN) false // 1.is 判斷兩個值是否相等 console.log(Object.is(1,1)); console.log(Object.is(0,-0));//返回false console.log(0 -0); console.log(Object.is(NaN,NaN)); console.log(NaN…

音樂曲譜軟件Guitar Pro 8.1.1 破解版下載和網盤補丁

Guitar Pro 8.1.1 for Mac 中文破解版是一款功能強大的音樂曲譜軟件&#xff0c;非常適合學習如何玩&#xff0c;改進技巧&#xff0c;重現喜愛的歌曲或陪伴自己。可以幫助我們進行吉他的學習、繪譜與創作&#xff0c;它包含了幾乎所有的吉他現有指法及音色&#xff0c;在做彈撥…

角谷定理 C語言xdoj32

角谷定理定義如下&#xff1a; 對于一個大于1的整數n&#xff0c;如果n是偶數&#xff0c;則n n / 2。如果n是奇數&#xff0c;則n 3 * n 1&#xff0c;反復操作后&#xff0c;n一定為1。 例如輸入22的變化過程&#xff1a; 22 ->11 -> 34 -> 17 -> 52 -> 26 …

電源小白入門學習3——電源系統常見元件選型MOS管、二極管、電感篇

電源小白入門學習3——電源系統常見元件選型MOS管、二極管、電感篇 MOS管二極管電感 書接上文&#xff0c;上一期我們講了電阻、電容選型中需要注意的事項&#xff0c;下面我們接著來介紹MOS管和二極管。 MOS管 關于MOS管的基本原理和內部的一些結構&#xff0c;PN結、半導體的…

FPGA 低延時 TCP UDP IP協議棧兼容1G 10G 25G MAC

在計算和數據中心、軍事和航天、政府、儀器與測量、金融服務和廣播和視頻等行業&#xff0c;需要高可靠性的硬件和軟件產品&#xff0c;幫助客戶更快地開發部署新一代產品&#xff0c;減少技術和市場風險&#xff0c;我司研發的低延遲TCP/IP的IP核的傳輸速率高于傳統網口&#…

游戲Undercut使用python代碼實現

游戲Undercut是一個紙牌游戲&#xff0c;兩位選手各有編號1-5的5張牌。每一輪中每個玩家選擇一張牌&#xff0c;然后依次出示各自的牌。如果兩張牌數相同&#xff0c;則沒有比分。另有兩種情況&#xff1a;兩張牌的數字只相差1&#xff08;這就是所謂的Undercut游戲&#xff09…

【工具類】Excel 多 Sheet 導入工具類

使用反射封裝&#xff0c;實現統一讀取 import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelTarget; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.…

創建個人網站(一)從零開始配置環境,搭建項目

目錄 前言配置環境前端后端遇到的問題1.安裝了nvm和node&#xff0c;vscode沒反應2.安裝完腳手架之后vue指令不存在 前言 從剛開始學前端的html直到現在前后端都有在開發&#xff0c;我一直都有一個想法&#xff0c;就是創建自己的網站&#xff0c;我相信大家都有這個想法&…

uni-app 設置當前page界面進入直接變為橫屏模式

首先 我們打開項目的 manifest.json 在左側導航欄中找到 源碼視圖 然后找到 app-plus 配置 在下面加上 "orientation": [//豎屏正方向"portrait-primary",//豎屏反方向"portrait-secondary",//橫屏正方向"landscape-primary",//橫屏…

99、NeRF ray space

CG相機模型 在圖形學中最常用的相機模型的原理和小孔成像是類似的。 不同之處在于&#xff0c;如上圖&#xff0c;小孔成像得到的圖像是倒立的&#xff0c;但是我們希望得到的圖像是正向的&#xff0c;因此&#xff0c;我們選擇小孔前成像。 從 3D 到 2D 的投影&#xff0c;…

Grad-CAM原理

這篇是我對嗶哩嗶哩up主 霹靂吧啦Wz 的視頻的文字版學習筆記 感謝他對知識的分享 只要大家一提到深度學習 缺乏一定的解釋性 比如說在我們之前講的分類網絡當中 網絡它為什么要這么預測 它針對每個類別所關注的點在哪里呢 在great cam這篇論文當中呢 就完美的解決了在cam這篇論…

java多線程(常用方法、實現方式、線程安全問題、生命周期、線程池)

多線程相關的三組概念 程序和進程 程序&#xff08;program&#xff09;&#xff1a;一個固定的運行邏輯和數據的集合&#xff0c;是一個靜態的狀態&#xff0c;一般存儲在硬盤中。簡單來說就是我們編寫的代碼 進程&#xff08;process&#xff09;&#xff1a;一個正在運行的…

Python 中的 queue 模塊隊列詳解;隊列如何使用——如何處理信息在多個線程間安全交換的多線程程序?

queue 模塊即隊列&#xff0c;特別適合處理信息在多個線程間安全交換的多線程程序中。下面我們對 queue 模塊進行一個詳細的使用介紹。 1 queue 模塊定義的類和異常 queue 模塊定義了以下四種不同類型的隊列&#xff0c;它們之間的區別在于數據入隊列之后出隊列的順序不同。 …

cmake編譯數據庫

在使用CMake進行編譯時&#xff0c;如果你想生成編譯數據庫&#xff0c;你可以定義CMAKE_EXPORT_COMPILE_COMMANDS選項。具體的命令如下&#xff1a; cmake -DCMAKE_EXPORT_COMPILE_COMMANDS1或者在CMakeLists.txt顯示的使能配置 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)這將會…

游戲玩家升級不傷手之選,光威龍武系列超強性能

得益于國產存儲芯片的崛起&#xff0c;現在的內存條價格太香了。要放在前幾年&#xff0c;購買內存條時都會優先考慮國際一線品牌。隨著內存條行業發生巨變&#xff0c;國產品牌光威GLOWAY&#xff0c;是全球前三的內存模組廠商嘉合勁威旗下品牌&#xff0c;它推出的內存條產品…

Zebec 推出由 Visa、萬事達網絡支持的即時支付卡,加密支付新征程

“Zebec現已推出全新的加密支付卡&#xff0c;該卡由Visa、萬事達網絡支持&#xff0c;具備即時、多鏈、非托管、無需KYC、免費等特性&#xff0c;其能夠通過加密錢包與多條主流公鏈鏈接并直接調用支付&#xff0c;這將是加密支付領域的里程碑事件。” 在2023年的12月8日&#…

C++中的string容器的substr()函數

一、作用 用來截取某段字符串。 二、頭文件 #include<string> 三、參數與用法 形式&#xff1a;s.substr(pos, len) 第一個參數是想要截取的字符串初始位置&#xff0c;第二個參數是截取字符串長度。 直接來說&#xff0c;就是從s[pos]開始截一個長度為len的子串。…