Java 9 đã kết hợp API trong một tập hợp các mô-đun. Do đó, tính mô-đun là chủ đề trung tâm; thiết kế chương trình bị ảnh hưởng này từ cấp cao nhất. Các chương trình có thể được xây dựng theo mô-đun ngay từ đầu. Không có gì ngạc nhiên khi sẽ có các API để xử lý cụ thể với phần tử lập trình được gọi là mô-đun . Các API cung cấp một cách để truy cập các mô-đun theo chương trình. Các API này khá tiện dụng để lấy thông tin cụ thể về các mô-đun hoặc đọc hoặc thao tác chúng. Bài viết này khám phá các lớp API mô-đun và một số phương pháp, với các ví dụ để cung cấp cho bạn ý tưởng về chức năng tổng thể của chúng.
Tổng quan
Java 9 cung cấp một tập hợp các lớp và giao diện để xử lý mô-đun theo chương trình. Các API này đặc biệt hữu ích cho:
- Đọc, tải và tìm kiếm các mô-đun
- Đọc và thao tác các bộ mô tả mô-đun
Danh sách các API được bao gồm chủ yếu trong các gói: java.lang và java.lang.module . Mặc dù java.lang.module gói bao gồm hầu hết các lớp và giao diện để xử lý các bộ mô tả mô-đun, java.lang gói chứa các lớp Mô-đun , ModuleLayer và một ngoại lệ, LayerInstantiationException . Trong số ba mô-đun này, Mô-đun lớp có tầm quan trọng hàng đầu vì một thể hiện của lớp này cung cấp tất cả các phương thức được kết nối với các mô-đun đọc, tải và tìm kiếm. Lớp quan trọng nhất trong java.lang.module gói là ModuleDescriptor . Lớp này cung cấp các phương thức cần thiết để xử lý các bộ mô tả mô-đun.
API mô-đun
Theo Tài liệu Java API, lớp mô-đun đại diện cho cả mô-đun thời gian chạy có tên và không tên. Mô-đun được đặt tên có tên và được Máy ảo Java xây dựng khi đồ thị mô-đun được xác định cho máy ảo Java để tạo lớp mô-đun. Một mô-đun không tên không có tên. Có một mô-đun chưa được đặt tên cho mỗi ClassLoader , có được bằng cách gọi getUnnameModule của nó phương pháp. Tất cả các loại không có trong mô-đun được đặt tên đều là thành viên của mô-đun không tên của trình tải lớp xác định của chúng.
Thật đơn giản để tìm ra mô-đun của một lớp mà nó thuộc về. Ví dụ:nếu chúng tôi muốn tìm ra mô-đun của một lớp, hãy nói, ArrayList , từ API Bộ sưu tập hoặc, chẳng hạn như Ứng dụng từ JavaFX, chúng tôi có thể làm như vậy theo cách sau.
Class<ArrayList> c= ArrayList.class; Module mod=c.getModule(); System.out.println(mod.getName());
Hoặc, trong một câu lệnh đơn lẻ, như sau:
System.out.println(Application.class .getModule().getName());
Thao tác này in tên mô-đun của lớp, chẳng hạn như java.base , cho Danh sách mảng và javafx.graphics cho Ứng dụng . Bởi vì một mô-đun có thể được đặt tên là chưa được đặt tên, chúng tôi có thể tìm ra bằng cách gọi isNamed () phương pháp. Phương thức này trả về true nếu mô-đun được đặt tên hoặc false nếu nó là một mô-đun không tên. Đây là một ví dụ về các mô-đun không tên.
package org.mano.java9.examples; public class Main { public static void main(String[] args) { Class<Main> c= Main.class; Module mod=c.getModule(); System.out.println(mod); System.out.println(mod.getName()); System.out.println(mod.getName()+" is " +(mod.isNamed()? "Named Module":"Unnamed Module")); System.out.println(mod.getDescriptor()); } }
Đầu ra:
unnamed module @4c75cab9 null null is Unnamed Module null
Và, đối với các mô-đun được đặt tên, chúng tôi có thể viết như sau:
package org.mano.java9.examples; import java.util.ArrayList; public class Main { public static void main(String[] args) { Class<ArrayList> c= ArrayList.class; Module mod=c.getModule();< System.out.println(mod); System.out.println(mod.getName()); System.out.println(mod.getName()+" is " +(mod.isNamed()? "Named Module":"Unnamed Module")); System.out.println(mod.getDescriptor()); } }
Đầu ra:
module java.base java.base java.base is Named Module module { name: [email protected], uses: [java.nio.file.spi.FileTypeDetector, ...}
A ModuleLayer chỉ chứa các mô-đun được đặt tên. Chúng tôi có thể gọi getLayer để lấy thông tin về lớp mà nó chứa trong mô-đun. Nếu nó trả về null, điều đó có nghĩa là mô-đun đó không nằm trong một lớp hoặc nó là một mô-đun chưa được đặt tên. Nếu chúng tôi muốn nhận danh sách các gói có sẵn trong một mô-đun, chúng tôi có thể gọi getPackages phương pháp. getClassLoader phương thức trả về trình nạp lớp mô-đun. Đây là một ví dụ để minh họa các phương pháp được mô tả ở trên.
package org.app.module1; import javafx.application.Application; import java.util.Set; public class Main { public static void main(String[] args) { Class<Application> c = Application.class; Module mod = c.getModule(); System.out.println("Name :" + mod.getName()); System.out.println(mod.getName() + " is " + (mod.isNamed() ? "Named Module" : "Unnamed Module")); System.out.println("Layer :" + mod.getLayer()); System.out.println("ClassLoader :" + mod.getClassLoader()); System.out.println("List of Packagesn....................."); Set<String> set = mod.getPackages(); int i=1; for (String s : set) { System.out.println(i+++") "+s); } } }
Đầu ra:
Name :javafx.graphics javafx.graphics is Named Module Layer :jdk.compiler, java.compiler, jdk.management.jfr, jdk.scripting.nashorn, ... ClassLoader :jdk.internal.loader.ClassLoaders [email protected] .................... List of Packages ..................... 1) com.sun.javafx.stage 2) com.sun.scenario.effect.impl.prism.ps 3) javafx.print ... 107) com.sun.prism.j2d 108) javafx.scene.image
Mô tả mô-đun
Theo Tài liệu API Java 9, “Bộ mô tả mô-đun mô tả một mô-đun được đặt tên và xác định các phương thức để lấy từng thành phần của nó”. Bộ mô tả mô-đun cho mô-đun đã đặt tên trong máy ảo Java được lấy bằng cách gọi Mô-đun ‘S getDescriptor phương pháp. Bộ mô tả mô-đun cũng có thể được tạo bằng cách sử dụng ModuleDescriptor.Builder lớp hoặc bằng cách đọc dạng nhị phân của khai báo mô-đun ( module-info.class ) bằng cách sử dụng đã đọc các phương thức được định nghĩa trong lớp này.
Do đó, thường là ModuleDescriptor phiên bản đại diện cho định nghĩa mô-đun được tìm thấy ở dạng nhị phân của tệp mô tả mô-đun, được gọi là module-info.class . Ngoài định nghĩa mô-đun đọc và thao tác, chúng ta có thể sử dụng ModuleDescriptor.Builder lớp để mô tả mô-đun tại thời điểm chạy.
Bộ mô tả mô-đun mô tả ba loại mô-đun, chẳng hạn như mô-đun bình thường, mở và tự động.
Mô-đun bình thường và mô-đun mở mô tả rõ ràng các dịch vụ mà chúng cung cấp hoặc sử dụng, các phần phụ thuộc, các gói được xuất và các thành phần khác. Sự khác biệt chính giữa mô-đun bình thường và mô-đun mở là Mô-đun bình thường có thể mở các gói cụ thể. Bộ mô tả mô-đun cho một mô-đun mở không khai báo bất kỳ gói nào đang mở ( mở phương thức trả về một tập hợp trống), nhưng khi được khởi tạo trong máy ảo Java, nó được coi như thể tất cả các gói đều đang mở.
Tuy nhiên, mô-đun tự động không khai báo bất kỳ gói được xuất, mở hoặc phụ thuộc nào ngoại trừ khai báo ngầm về java.base mô-đun. Khi một mô-đun tự động được khởi tạo trong máy ảo Java, nó sẽ đọc mọi mô-đun chưa được đặt tên và được coi như thể tất cả các gói đều được xuất và mở.
getDescriptor phương pháp của Mô-đun lớp trả về một bản sao của ModuleDescriptor lớp. ModuleDescriptor lớp chứa các lớp lồng nhau tĩnh mà cá thể của nó đại diện cho câu lệnh chỉ thị trong tệp khai báo mô-đun. Tuy nhiên, lớp này không chứa các công dụng câu lệnh thường có thể được đại diện bởi một phiên bản dịch vụ Chuỗi . Đây là bốn thứ khác:
- ModuleDescriptor.Requires
- ModuleDescriptor.Open
- ModuleDescriptor.Provides
- ModuleDescriptor.Exports
Một ví dụ nhanh
package org.mano.java9.examples; import javax.sql.RowSet; import java.lang.module.ModuleDescriptor; import java.util.List; public class Main { public static void main(String[] args) { System.out.println("Module Name: " + List.class.getModule().getName()); show(List.class.getModule().getDescriptor()); System.out.println("Module Name: " + RowSet.class.getModule().getName()); show(RowSet.class.getModule().getDescriptor()); } public static void show(ModuleDescriptor d) { System.out.println("Module Descriptionn-------------------------"); System.out.println("Requires: " + d.requires()); System.out.println("Exports: " + d.exports()); System.out.println("Uses: " + d.uses()); System.out.println("Provides: " + d.provides()); System.out.println("Packages: " + d.packages()); } }
Đầu ra:
Module Name: java.base Module Description ------------------------- Requires: [] Exports: [jdk.internal.org.objectweb.asm.signature to [jdk.scripting.nashorn], ...] Uses: [java.util.spi.LocaleNameProvider, java.nio.file.spi.FileSystemProvider, ...] Provides: [java.nio.file.spi.FileSystemProvider with [jdk.internal.jrtfs.JrtFileSystemProvider]] Packages: [java.nio.file, jdk.internal.org.objectweb.asm .tree.analysis, com.sun.security.ntlm, ...] Module Name: java.sql Module Description ------------------------- Requires: [mandated java.base, transitive java.logging, transitive java.xml] Exports: [java.sql, javax.transaction.xa, javax.sql] Uses: [java.sql.Driver] Provides: [] Packages: [javax.sql, javax.transaction.xa, java.sql]
Tệp nhị phân của bộ mô tả mô-đun, được gọi là module-info.class , có thể được đọc trực tiếp theo cách sau để tạo một phiên bản của ModuleDescriptor lớp:
try { ModuleDescriptor descriptor = ModuleDescriptor .read(new FileInputStream("module-info.class")); } catch (IOException ex) { }
Có bốn phiên bản của static read bị quá tải được xác định trong ModuleDescriptor lớp. Chúng được sử dụng để đọc dạng nhị phân của mô tả mô-đun từ luồng đầu vào hoặc bộ đệm byte. Đây là phần trích xuất từ tài liệu Java 9 API.
- đọc (InputStream in) :Đọc dạng nhị phân của khai báo mô-đun từ luồng đầu vào dưới dạng bộ mô tả mô-đun.
- đọc (InputStream in, Nhà cung cấp
> packageFinder) :Đọc dạng nhị phân của khai báo mô-đun từ luồng đầu vào dưới dạng bộ mô tả mô-đun. - đã đọc (ByteBuffer bb) :Đọc dạng nhị phân của khai báo mô-đun từ bộ đệm byte dưới dạng bộ mô tả mô-đun.
- đọc (ByteBuffer bb, Nhà cung cấp
> packageFinder) :Đọc dạng nhị phân của khai báo mô-đun từ bộ đệm byte dưới dạng bộ mô tả mô-đun.
Các gói được đặt bởi packageFinder bao gồm tất cả các gói mà mô-đun xuất, mở, các dịch vụ được cung cấp và gói của lớp chính không được mã hóa bởi bộ mô tả được cung cấp trong luồng đầu vào hoặc bộ đệm byte.
Kết luận
Ngoài việc đọc thông tin cơ bản về mô-đun, Mô-đun lớp cung cấp một số phương thức chính để hỏi về trạng thái mô-đun — liệu nó có được đọc, mở, xuất, v.v. hay không. API cũng cung cấp các phương thức như addOpens , addExport , addUses và addReads để thêm các sử dụng mở và xuất cũng như đọc các câu lệnh vào bộ mô tả mô-đun theo chương trình. Tóm lại, API mô-đun cung cấp nhiều phương pháp khác để xử lý cụ thể các mô-đun theo chương trình. Ở đây, chúng tôi mới chỉ sơ lược bề ngoài để đưa ra ý tưởng ban đầu về nội dung của nó.