摘要:例子中的文件路徑使用斜杠,路徑分隔符是冒號。到目前為止的示例中,已編譯的模塊的內容在文件系統上以分散的文件的形式存儲。當用于分發和部署時通常更方便的方式是將一個模塊打包成一個模塊化的。在這個例子中,模塊打包時表明了它的版本是。
本文檔提供了幾個簡單的例子,讓開發人員開始使用模塊。
例子中的文件路徑使用斜杠,路徑分隔符是冒號。使用微軟Windows開發的人員應該使用文件路徑以反斜杠和一個分號作為路徑分隔符。
Greetings第一個例子是一個只打印“Greetings!”命名為com.greetings的模塊。該模塊包括兩個源文件:模塊聲明文件(module-info.java)和Main.java
按慣例,模塊的源代碼在一個目錄中,該目錄是模塊的名稱:
src/com.greetings/com/greetings/Main.java src/com.greetings/module-info.java $ cat src/com.greetings/module-info.java module com.greetings { } $ cat src/com.greetings/com/greetings/Main.java package com.greetings; public class Main { public static void main(String[] args) { System.out.println("Greetings!"); } }
使用以下命令,將源碼編譯到 mods/com.greetings 目錄下:
$ mkdir -p mods/com.greetings $ javac -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java
現在我們用下面的命令運行這個例子:
$ java -modulepath mods -m com.greetings/com.greetings.Main
-modulepath是模塊的路徑,它的值是一個或多個包含模塊的目錄。-m 選項指定了主模塊,在/后的值是模塊主類包含包名的完整名稱。
Greetings world第二個示例是在之前示例的基礎上增加了org.astro模塊依賴,模塊org.astro提供org.astro包的API。
src/org.astro/module-info.java src/org.astro/org/astro/World.java src/com.greetings/com/greetings/Main.java src/com.greetings/module-info.java $ cat src/org.astro/module-info.java module org.astro { exports org.astro; } $ cat src/org.astro/org/astro/World.java package org.astro; public class World { public static String name() { return "world"; } } $ cat src/com.greetings/module-info.java module com.greetings { requires org.astro; } $ cat src/com.greetings/com/greetings/Main.java package com.greetings; import org.astro.World; public class Main { public static void main(String[] args) { System.out.format("Greetings %s!%n", World.name()); } }
該模塊編譯,在同一時間。使用javac命令指定模塊路徑編譯模塊com.greetings,并有模塊org.astro的引用,這樣可以獲取到org.astro提供的API。
$ mkdir mods/org.astro mods/com.greetings $ javac -d mods/org.astro src/org.astro/module-info.java src/org.astro/org/astro/World.java $ javac -modulepath mods -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java
該示例以與第一個示例完全相同的方式運行:
$ java -modulepath mods -m com.greetings/com.greetings.Main Greetings world!多模塊編譯
在前面的示例,模塊 com.greetings 和模塊 org.astro 是分別編譯的。使用javac 命令編譯模塊時還可以一次編譯多個模塊。
$ mkdir mods $ javac -d mods -modulesourcepath src $(find src -name "*.java") $ find mods -type f mods/com.greetings/com/greetings/Main.class mods/com.greetings/module-info.class mods/org.astro/module-info.class mods/org.astro/org/astro/World.classPackaging
到目前為止的示例中,已編譯的模塊的內容在文件系統上以分散的文件的形式存儲。當用于分發和部署時通常更方便的方式是將一個模塊打包成一個模塊化的JAR。一個模塊化的JAR是一個普通的jar文件中在頂級目錄有一個module-info.class。下面的示例在mlib目錄org.astro@1.0.jar和com.greetings.jar。
$ mkdir mlib $ jar --create --file=mlib/org.astro@1.0.jar --module-version=1.0 -C mods/org.astro . $ jar --create --file=mlib/com.greetings.jar --main-class=com.greetings.Main -C mods/com.greetings . $ ls mlib com.greetings.jar org.astro@1.0.jar
在這個例子中,org.astro模塊打包時表明了它的版本是1.0 (--module-version=1.0)。模塊com.greetings在打包時表明其主類是com.greetings.Main (--main-class=com.greetings.Main)。我們現在可以執行模塊com.greetings而無需指定其主類:
$ java -mp mlib -m com.greetings Greetings world!
上面的命令中使用了 -modulepath 的簡寫 -mp 。
jar工具增加了很多新的選項(可以通過jar -help查看),其中之一是打印一個模塊jar的模塊聲明:
原文中給出的是:
$ jar --print-module-descriptor --file=mlib/org.astro@1.0.jar Name: org.astro@1.0 Requires: java.base [ MANDATED ] Exports: org.astro
但我實際在Windows下測試的結果為:
C:UserscoderknockworkspaceJDK9>jar --print-module-descriptor --file=mliborg.astro@1.0.jar org.astro@1.0 requires mandated java.base exports org.astro C:UserscoderknockworkspaceJDK9>jar --print-module-descriptor --file=mlibcom.greetings.jar com.greetings requires mandated java.base requires org.astro conceals com.greetings main-class com.greetings.Main缺少requires(依賴) 或者exports(輸出)
如果我們在上一個示例中在com.greetings module的模塊聲明中沒有設定依賴org.astro,讓我們看看會發生什么:
$ cat src/com.greetings/module-info.java module com.greetings { // requires org.astro; } $ javac -modulepath mods -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java src/com.greetings/com/greetings/Main.java:2: 錯誤: 程序包org.astro不存在 import org.astro.World; ^ src/com.greetings/com/greetings/Main.java:5: 錯誤: 找不到符號 System.out.format("Greetings %s!%n", World.name()); ^ 符號: 變量 World 位置: 類 Main 2 個錯誤
現在我們試一下,com.greetings聲明了依賴,但是org.astro沒有聲明輸出會發生什么:
$ cat src/com.greetings/module-info.java module com.greetings { requires org.astro; } $ cat src/org.astro/module-info.java module org.astro { // exports org.astro; } $ javac -modulepath mods -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java src/com.greetings/com/greetings/Main.java:2: 錯誤: 程序包org.astro不存在 import org.astro.World; ^ src/com.greetings/com/greetings/Main.java:5: 錯誤: 找不到符號 System.out.format("Greetings %s!%n", World.name()); ^ 符號: 變量 World 位置: 類 Main 2 個錯誤服務
服務允許服務消費者模塊和服務提供商模塊之間的松散耦合。
這個例子有一個服務消費模塊和一個服務提供模塊:
模塊com.socket輸出了一個網絡套接字的API。API被封裝在com.socket包,所以這個包是輸出者。API是可插拔的,允許替換具體的實現。com.socket.spi.networksocketprovider是實際提供服務的抽象類,所以com.socket.spi也應該被輸出。
org.fastsocket模塊是一個服務提供模塊,它提供了一個com.socket.spi.NetworkSocketProvider的實現,不需要輸出。
下面是 com.socket 模塊的源碼:
$ cat src/com.socket/module-info.java module com.socket { exports com.socket; exports com.socket.spi; uses com.socket.spi.NetworkSocketProvider; } $ cat src/com.socket/com/socket/NetworkSocket.java package com.socket; import java.io.Closeable; import java.util.Iterator; import java.util.ServiceLoader; import com.socket.spi.NetworkSocketProvider; public abstract class NetworkSocket implements Closeable { protected NetworkSocket() { } public static NetworkSocket open() { ServiceLoadersl = ServiceLoader.load(NetworkSocketProvider.class); Iterator iter = sl.iterator(); if (!iter.hasNext()) throw new RuntimeException("No service providers found!"); NetworkSocketProvider provider = iter.next(); return provider.openNetworkSocket(); } } $ cat src/com.socket/com/socket/spi/NetworkSocketProvider.java package com.socket.spi; import com.socket.NetworkSocket; public abstract class NetworkSocketProvider { protected NetworkSocketProvider() { } public abstract NetworkSocket openNetworkSocket(); }
下面是org.fastsocket模塊的源碼:
$ cat src/org.fastsocket/module-info.java module org.fastsocket { requires com.socket; provides com.socket.spi.NetworkSocketProvider with org.fastsocket.FastNetworkSocketProvider; } $ cat src/org.fastsocket/org/fastsocket/FastNetworkSocketProvider.java package org.fastsocket; import com.socket.NetworkSocket; import com.socket.spi.NetworkSocketProvider; public class FastNetworkSocketProvider extends NetworkSocketProvider { public FastNetworkSocketProvider() { } @Override public NetworkSocket openNetworkSocket() { return new FastNetworkSocket(); } } $ cat src/org.fastsocket/org/fastsocket/FastNetworkSocket.java package org.fastsocket; import com.socket.NetworkSocket; class FastNetworkSocket extends NetworkSocket { FastNetworkSocket() { } public void close() { } }
為了簡單起見,我們一起編譯這兩個模塊。在實踐中,服務消費模塊和服務提供模塊幾乎總是多帶帶編譯。
$ mkdir mods $ javac -d mods -modulesourcepath src $(find src -name "*.java")
最后我們修改一下com.greetings模塊,在其Main中使用上面提供出的API:
$ cat src/com.greetings/module-info.java module com.greetings { requires com.socket; } $ cat src/com.greetings/com/greetings/Main.java package com.greetings; import com.socket.NetworkSocket; public class Main { public static void main(String[] args) { NetworkSocket s = NetworkSocket.open(); System.out.println(s.getClass()); } } $ javac -d mods/com.greetings/ -mp mods $(find src/com.greetings/ -name "*.java")
最后,我們運行一下:
$ java -mp mods -m com.greetings/com.greetings.Main class org.fastsocket.FastNetworkSocket
輸出結果表明服務提供者已經找到,而且使用的是NetworkSocket工廠,實現是FastNetworkSocketProvider。
鏈接器jlink 是連接器工具,用來連接一組模塊 ,連同他們的依賴關系,創建一個自定義模塊運行時鏡像( JEP 220規范定義)。
該工具目前需要的封裝成模塊JAR或者JMOD格式的模塊的路徑。JDK中將一些標準以及JDK特性包裝成JMOD格式(在JDK安裝目錄的jmods目錄下)。
下面的示例創建一個運行時鏡像包含模塊com.greetings以及傳遞相關的依賴:
jlink --modulepath $JAVA_HOME/jmods:mlib --addmods com.greetings --output greetingsapp
--modulepath 是包含將要打包的模塊的模塊路徑(示例中$JAVA_HOME/jmods是JDK內置的模塊,所有模塊默認引入有java.base模塊的依賴,java.base在$JAVA_HOME/jmods中),Linux目錄分隔符是:Windows是;按照自己的環境修改“jmods:mlib”的符號。(我在本地測試這個沒有成功,有成功的同學請留言)
$JAVA_HOME/jmods是java.base.jmod的模塊路徑同時包含別的JDK模塊.。如果你是自己編譯的OpenJDK,那么應該使用 $BUILDOUTPUT/images/jmods, $BUILDOUTPUT 指的是你設置的編譯輸出目錄。
在模塊路徑設置里的目錄mlib包含模塊com.greetings。
jlink工具支持許多高級選項自定義生成的鏡像, jlink --help查看更多選項。
我是廣告本人的直播課程在 7 月份就要開始了,希望小伙伴們支持一下,現在報名有優惠噢
https://segmentfault.com/l/15...
https://segmentfault.com/l/15...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67218.html
摘要:的主要新特性表達式允許把函數作為一個方法的參數傳遞進方法中。作用解決被詬病的匿名內部類的問題。新特性模塊系統模塊是一個包的容器,最大的變化之一是引入模塊系統。支持標準標準是協議的最新版本,新的支持和流以及服務器推送特性。 Java 8 的主要新特性 1. Lambda 表達式 Lambda 允許把函數作為一個方法的參數傳遞進方法中。 作用:解決 Java 被詬病的匿名內部類的問題。 2...
摘要:本書概括以軟件系統為例,重點講解了應用架構中的物理設計問題,即如何將軟件系統拆分為模塊化系統。容器獨立模塊不依賴于具體容器,采用輕量級容器,如獨立部署模塊可獨立部署可用性模式發布接口暴露外部配置使用獨立的配置文件用于不同的上下文。 本文為讀書筆記,對書中內容進行重點概括,并將書中的模塊化結合微服務、Java9 Jigsaw談談理解。 本書概括 以Java軟件系統為例,重點講解了應用架構...
摘要:什么是項目是第一個官方的的縮寫,即交互式編程環境,是一種命令行工具。它允許你無需編寫類或者方法來執行語句。它與的解釋器或其它本地支持的語言,如和類似。在即將到來的的特性中,這絕對是更有趣的特性之一。 什么是JShell? JShell/Kulla項目是第一個官方的Java REPL (Read-Eval-Print-Loop的縮寫,即交互式編程環境),是一種命令行工具。它允許你無需編寫...
摘要:新特性概述系列一安裝及使用系列二運行系列三模塊系統精要系列四更新系列五系列六系列七系列八系列九與的區別遷移注意事項參數遷移相關選項解析使用構建實例使用示例帶你提前了解中的新特性 Java語言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新特性 Java12的新特性 Java13的新特性...
摘要:的核心變化就是引入了一種新的編程組件,也就是模塊,按照的說法,它是一個可命名的自描述的代碼和數據集合。宣布會按照每六個月一次的節奏進行發布,意味著是最后一次特性驅動的版本發布,這反映出了目前管理的特點。 Java SE 9.0于2017年9月21日發布。JDK 9的核心變化就是引入了一種新的Java編程組件,也就是模塊,按照Oracle的說法,它是一個可命名的、自描述的代碼和數據集合。...
閱讀 2397·2021-10-09 09:44
閱讀 2132·2021-10-08 10:05
閱讀 3424·2021-07-26 23:38
閱讀 2991·2019-08-28 18:16
閱讀 812·2019-08-26 11:55
閱讀 1820·2019-08-23 18:29
閱讀 2034·2019-08-23 18:05
閱讀 1364·2019-08-23 17:02