Java语言规范基于JavaSE9 第七章 包和模块(八)

来源:互联网 发布:php base64解码后乱码 编辑:程序博客网 时间:2024/06/09 15:23

7.7 Module Declarations

7.7 模块声明

A module declaration specifies a new named module. A named module specifies dependences on other modules to define the universe of classes and interfaces available to its own code; and specifies which of its packages are exported or opened in order to populate the universe of classes and interfaces available to other modules which specify a dependence on it.

模块声明指定了一个新的具名模块。具名模块指定了对其他模块的依赖关系,以定义可用于其自己的代码的类和接口的范围;并且指定将其中哪些包导出或打开,以便填充对指定与其有依赖性的其他模块的可用类和接口的范围。

A “dependence” is what is expressed by a requires directive, independent of whether a module exists with the name specified by the directive. A “dependency” is the observable module enumerated by resolution (as described in the java.lang.module package specification) for a given requires directive. Generally, the rules of the Java programming language are more interested in dependences than dependencies.

“依赖”是指由需求指令表示的内容,与模块是否存在指令指定的名称无关。“依赖关系”是指根据给定的需求指令决定(如java.lang.module包规范中所述)而枚举出可观察模块。通常来讲,Java编程语言的规则更注重依赖而不是依赖关系。

ModuleDeclaration:
{Annotation} [open] module Identifier {. Identifier}
  { {ModuleDirective} }

A module declaration introduces a module name that can be used in other module declarations to express relationships between modules. A module name consists of one or more Java identifiers (§3.8) separated by “.” tokens.

模块声明引入了一个模块名称,它可以在其他模块声明中使用来表示模块之间的关系。模块名称由一个或多个Java标识符(第3.8节)通过符号“.”分隔组成。

There are two kinds of modules: normal modules and open modules. The kind of a module determines the nature of access to the module’s types, and the members of those types, for code outside the module.

模块有两种种类:正常模块和开放模块。模块的种类决定了对模块类型的访问的性质,以及这些类型的成员对模块外的代码的性质。

A normal module, without the open modifier, grants access at compile time and run time to types in only those packages which are explicitly exported.

不带有open修饰符的普通模块在编译时和运行时只允许访问显式导出的包中的类型。

An open module, with the open modifier, grants access at compile time to types in only those packages which are explicitly exported, but grants access at run time to types in all its packages, as if all packages had been exported.

带有open修饰符的开放模块在编译时只允许访问显式导出的包中的类型;而在运行时允许访问模块中所有包的类型,就像所有包都被导出一样。

For code outside a module (whether the module is normal or open), the access granted at compile time or run time to types in the module’s exported packages is specifically to the public and protected types in those packages, and the public and protected members of those types (§6.6). No access is granted at compile time or run time to types, or their members, in packages which are not exported. Code inside the module may access public and protected types, and the public and protected members of those types, in all packages in the module at both compile time and run time.

对于模块(无论是普通模块还是开放模块)外代码来说,在编译时或运行时,允许访问的模块导出包中的类型具体为这些包中的public和protected类型以及这些类型中的public和protected成员;不允许访问模块中不是导出包的类型或者它们的成员。模块内代码在编译时和运行时可以访问模块中所有包的public和protected类型以及这些类型中的public和protected成员。

Distinct from access at compile time and access at run time, the Java SE Platform provides reflective access via the Core Reflection API (§1.4). A normal module grants reflective access to types in only those packages which are explicitly exported or explicitly opened (or both). An open module grants reflective access to types in all its packages, as if all packages had been opened.

与编译时访问和运行时访问不同,Java SE平台通过核心反射API(第1.4节)提供了反射访问。普通模块只允许反射访问模块中那些显式导出或显式开放(或两者)的包中的类型。开放模块允许反射访问模块中的所有包中的类型,就像所有包都被导出一样。

For code outside a normal module, the reflective access granted to types in the module’s exported (and not opened) packages is specifically to the public and protected types in those packages, and the public and protected members of those types. The reflective access granted to types in the module’s opened packages (whether exported or not) is to all types in those packages, and all members of those types. No reflective access is granted to types, or their members, in packages which are not exported or opened. Code inside the module enjoys reflective access to all types, and all their members, in all packages in the module.

对于普通模块外代码来说,允许反射访问模块的导出(不是开放)包中的类型具体为这些包中的public和protected类型以及这些类型中的public和protected成员;允许反射访问模块的开放包(无论是否导出)中的所有类型以及这些类型中的所有成员;不允许反射访问那些模块中不是导出或开放的包的类型或它们的成员。模块内代码能够反射访问模块中所有包中的所有类型以及它们所有的成员。

For code outside an open module, the reflective access granted to types in the module’s opened packages (that is, all packages in the module) is to all types in those packages, and all members of those types. Code inside the module enjoys reflective access to all types, and all their members, in all packages in the module.

对于开放模块外代码来说,允许反射访问模块的开放包(即模块中的所有包)中的所有类型以及这些类型中的所有成员。模块内代码能够反射访问模块中所有包中的所有类型以及它们的所有成员。

The directives of a module declaration specify the module’s dependences on other modules (via requires, §7.7.1), the packages it makes available to other modules (via exports and opens, §7.7.2), the services it consumes (via uses, §7.7.3), and the services it provides (via provides, §7.7.4).

模块声明的指令指定了模块对其他模块的依赖(通过requires指令,第7.7.1节);它对其他模块可用的包(通过exports和opens指令,第7.7.2节);它使用的服务(通过uses指令,第7.7.3节);它提供的服务(通过provides指令,第7.7.4节)。

ModuleDirective:
requires {RequiresModifier} ModuleName ;
exports PackageName [to ModuleName {, ModuleName}] ;
opens PackageName [to ModuleName {, ModuleName}] ;
uses TypeName ;
provides TypeName with TypeName {, TypeName} ;

RequiresModifier:
(one of)
transitive static

If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a module declaration is not found in a file under a name composed of module-info plus an extension (such as .java or .jav).

当且仅当包存储在文件系统(第7.2节)中时,如果在由module-info加上扩展名(例如.java或.jav)组成的名称的文件中找不到模块声明,则主机系统可能会强制产生一个编译时错误。

To aid comprehension, it is customary, though not required, for a module declaration to group its directives, so that the requires directives which pertain to modules are visually distinct from the exports and opens directives which pertain to packages, and from the uses and provides directives which pertain to services. For example:

为了帮助理解,习惯上(尽管不是必需的)在模块声明中对其指令进行分组,以便让与模块有关的requires指令、与包有关的exports和opens指令、与服务有关的的uses和provides指令看起来有所区分。例如:

module com.example.foo {    requires com.example.foo.http;     requires java.logging;    requires transitive com.example.foo.network;     exports com.example.foo.bar;    exports com.example.foo.internal to com.example.foo.probe;    opens com.example.foo.quux;    opens com.example.foo.internal to com.example.foo.network,    com.example.foo.probe;    uses com.example.foo.spi.Intf;    provides com.example.foo.spi.Intf with com.example.foo.Impl;}

The opens directives can be avoided if the module is open:

如果模块是开放的,那么opens指令可以避免。

open module com.example.foo {     requires com.example.foo.http;     requires java.logging;    requires transitive com.example.foo.network;     exports com.example.foo.bar;    exports com.example.foo.internal to com.example.foo.probe;    uses com.example.foo.spi.Intf;    provides com.example.foo.spi.Intf with com.example.foo.Impl;}

Development tools for the Java programming language are encouraged to highlight requires transitive directives and unqualified exports directives, as these form the primary API of a module.

建议Java程序语言开发工具高亮显示来自模块的主API的 requires transitive指令和非限定的exports指令。

7.7.1 Dependences

7.7.1 依赖

The requires directive specifies the name of a module on which the current module has a dependence.

requires指令指定了被当前模块依赖的模块的名称。

A requires directive must not appear in the declaration of the java.base module, or a compile-time error occurs, because it is the primordial module and has no dependences (§8.1.4).

requires指令不能在java.base模块声明出现,否则会发生编译时错误,因为该模块是初始模块不存在依赖关系。

If the declaration of a module does not express a dependence on the java.base module, and the module is not itself java.base, then the module has an implicitly declared dependence on the java.base module.

如果模块声明不明确表示对java.base模块的依赖,并且该模块不是java.base本身,那么该模块隐式声明依赖于java.base模块。

The requires keyword may be followed by the modifier transitive. This causes any module which requires the current module to have an implicitly declared dependence on the module specified by the requires transitive directive.

requires关键字后可以跟着修饰符transitive。这将导致依赖于当前模块的任何模块隐式地依赖于被requires transitive指令指定的模块。

The requires keyword may be followed by the modifier static. This specifies that the dependence, while mandatory at compile time, is optional at run time.

requires关键字后可以跟着修饰符static。这样就指定了依赖的模块在编译时是必需的,而在运行时是可选的。

It is a compile-time error if more than one requires directive in a module declaration specifies the same module name.

如果在模块声明中有多个requires指令指定了相同的模块名,则会产生编译时错误。

It is a compile-time error if resolution, as described in the java.lang.module package specification, with the current module as the only root module, fails for any of the reasons described in the java.lang.module package specification.

如果像在java.lang.module包规范中描述的解决方案一样,当前模块作为唯一的根模块,由于java.lang.module包规范中描述的任何原因而失败,那么会产生编译时错误。

For example, if a requires directive specifies a module that is not observable, or if the current module directly or indirectly expresses a dependence on itself.

例如,如果requires指令指定了一个不可观察的模块,或者当前模块直接或间接地表示了对自身的依赖。

If resolution succeeds, then its result specifies the modules that are read by the current module. The modules read by the current module determine which ordinary compilation units are visible to the current module (§7.3). The types declared in those ordinary compilation units (and only those ordinary compilation units) may be accessible to code in the current module (§6.6).

如果解析成功,则其结果是指定由当前模块读取的模块。当前模块读取的模块能够确定哪些普通编译单元对当前模块可见(第7.3节)。在那些普通编译单元中声明的类型(仅限那些普通编译单元)可以被当前模块(第6.6节)中的代码访问。

The Java SE Platform distinguishes between named modules that are explicitly declared (that is, with a module declaration) and named modules that are implicitly declared (that is, automatic modules). However, the Java programming language does not surface the distinction: requires directives refer to named modules without regard for whether they are explicitly declared or implicitly declared.

Java SE平台区分显式声明的具名模块(即模块声明)和隐式声明的具名模块(即自动模块)。但是,Java编程语言并没有表现出这样的区别:requires指令引用指定的具名模块,而不考虑它们是否被显式声明或隐式声明。

While automatic modules are convenient for migration, they are unreliable in the sense that their names and exported packages may change when their authors convert them to explicitly declared modules. A Java compiler is encouraged to issue a warning if a requires directive refers to an automatic module. An especially strong warning is recommended if the transitive modifier appears in the directive.

虽然自动模块便于迁移,但是它们的名称和导出包可能在其作者将它们转换成显式声明的模块时发生改变,所以它们是不可靠的。建议Java编译器在requires指令引用了自动模块时发出警告。如果transitive修饰符出现在指令中的话,则建议使用特强级别的警告。

Example 7.1.1-1. Resolution of requires transitive directives

例7.1.1-1. requires transitive指令解决方案

Suppose there are four module declarations as follows:

假设有4个模块声明如下:

module m.A {    requires m.B;}module m.B {    requires transitive m.C;}module m.C {    requires transitive m.D;}module m.D {    exports p;}

where the package p exported by m.D is declared as follows:

其中由m.D导出的包p的声明如下:

package p;public class Point {}

and where a package client in module m.A refers to the public type Point in the exported package p:

以及模块m.A中的包client引用导出的包p中的public类型Point:

package client; import p.Point; public class Test {    public static void main(String[] args) {         System.out.println(new Point());    }}

The modules may be compiled as follows, assuming that the current directory has one subdirectory per module, named after the module it contains:

假设当前目录下每个模块有一个子目录,以其包含的模块命名,模块可能编译如下:

javac --module-source-path . -d . --module m.D javac --module-source-path . -d . --module m.Cjavac --module-source-path . -d . --module m.B javac --module-source-path . -d . --module m.A

The program client.Test may be run as follows:

程序client.Test可能运行如下:

java --module-path . --module m.A/client.Test

The reference from code in m.A to the exported public type Point in m.D is legal because m.A reads m.D, and m.D exports the package containing Point. Resolution determines that m.A reads m.D as follows:

m.A中的代码对m.D中导出的public类型Point的引用是合法的,因为m.A读取m.D,并且m.D导出了包含Point的包。确定m.A读取m.D的解决方案如下:

• m.A requires m.B and therefore reads m.B.

• m.A requires m.B因此读取m.B。

• Since m.A reads m.B, and since m.B requires transitive m.C, resolution determines that m.A reads m.C.

• 由于m.A读取m.B而且m.B requires transitive m.C,解决方案确定m.A读取m.C。

• Then, since m.A reads m.C, and since m.C requires transitive m.D, resolution determines that m.A reads m.D.

• 那么,由于m.A读取m.C而且m.C requires transitive m.D,解决方案确定m.A读取m.D。

In effect, a module may read another module through multiple levels of dependence, in order to support arbitrary amounts of refactoring. Once a module is released for someone to reuse (via requires), the module’s author has committed to its name and API but is free to refactor its content into other modules which the original module reuses (via requires transitive) for the benefit of consumers. In the example above, package p may have been exported originally by m.B (thus, m.A requires m.B) but refactoring has caused some of m.B’s content to move into m.C and m.D. By using a chain of requires transitive directives, the family of m.B, m.C, and m.D can preserve access to package p for code in m.A without forcing any changes to the requires directives of m.A. Note that package p in m.D is not “re-exported” by m.C and m.B; rather, m.A is made to read m.D directly.

实际上,模块可以通过多个级别的依赖来读取另一个模块,以支持任意数量的重构。一旦一个模块被发布以供他人复用(通过requires),模块的作者承诺模块名和API可以自由重写它的内容到那些为了消费者的利益而重用(通过requires transitive)初始模块的其他模块。在上面的例子中,包p可能原本是由m.B导出的(因此,m.A requires m.B),但是重构导致了m.B的一些内容迁移到了m.C和m.D。通过使用requires transitive指令链,m.B、m.C和m.D的属族可以对m.A中的代码保留访问包p的权限,而无需强制对m.A的requires指令进行任何更改。注意,m.D中的包p不是由m.C和m.B“重导出”的;相反,m.A是直接读取m.D的。

7.7.2 Exported and Opened Packages

7.7.2 导出和开放包

The exports directive specifies the name of a package to be exported by the current module. For code in other modules, this grants access at compile time and run time to the public and protected types in the package, and the public and protected members of those types (§6.6). It also grants reflective access to those types and members for code in other modules.

exports指令指定了当前模块要导出的包的名称。对于其他模块的代码来说,这将允许它们在编译时和运行时访问包中的public和protected类型,以及这些类型(第6.6节)中的public和protected成员。同样的,也允许它们反射访问这些类型和成员。

The opens directive specifies the name of a package to be opened by the current module. For code in other modules, this grants access at run time, but not compile time, to the public and protected types in the package, and the public and protected members of those types. It also grants reflective access to all types in the package, and all their members, for code in other modules.

opens指令指定了当前模块要开放的包的名称。对于其他模块的代码来说,这将允许它们在运行时(而不是编译时)访问包中的public和protected类型,以及这些类型的public和protected成员。同样的,也允许它们反射访问包中的所有类型以及类型的所有成员。

It is a compile-time error if the package specified by exports is not declared by a compilation unit associated with the current module (§7.3).

如果由exports指定的包未被与当前模块关联的编译单元(第7.3节)声明的话,会发生编译时错误。

It is permitted for opens to specify a package which is not declared by a compilation unit associated with the current module. (If the package should happen to be declared by an observable compilation unit associated with another module, the opens directive has no effect on that other module.)

用opens来指定未被与当前模块关联的编译单元所声明的包是合法的(如果包恰好被其他模块关联的可观察编译单元声明了,那么opens指令将不会对那些模块起作用)。

It is a compile-time error if more than one exports directive in a module declaration specifies the same package name.

如果模块声明中存在多个exports指令指定同样的包名,则会产生编译时错误。

It is a compile-time error if more than one opens directive in a module declaration specifies the same package name.

如果模块声明中存在多个opens指令指定同样的包名,则会产生编译时错误。

It is a compile-time error if an opens directive appears in the declaration of an open module.

如果在开放模块的声明中出现opens指令,则会产生编译时错误。

If an exports or opens directive has a to clause, then the directive is qualified; otherwise, it is unqualified. For a qualified directive, the public and protected types in the package, and their public and protected members, are accessible solely to code in the modules specified in the to clause. The modules specified in the to clause are referred to as friends of the current module. For an unqualified directive, these types and their members are accessible to code in any module.

如果exports或者opens指令有to子句,那么该指令是限定的;否则就是非限定的。对于限定指令来说,包中的public和protected类型以及这些类型的public和protected成员只能被to子句中指定的模块的代码所访问。to子句中指定的模块被称为当前模块的friends。对于非限定指令来说,任何模块的代码都能访问这些类型和它们的成员。

It is permitted for the to clause of an exports or opens directive to specify a module which is not observable (§7.7.6).

用exports或者opens指令的to子句指定不可观察(第7.7.6节)的模块是合法的。

It is a compile-time error if the to clause of a given exports directive specifies the same module name more than once.

如果给定的exports指令的to子句多次指定相同的模块名,则会产生编译时错误。

It is a compile-time error if the to clause of a given opens directive specifies the same module name more than once.

如果给定的opens指令的to子句多次指定相同的模块名,则会产生编译时错误。

7.7.3 Service Consumption

7.7.3 服务消费

The uses directive specifies a service for which the current module may discover providers via java.util.ServiceLoader.

uses指令指定当前模块可以通过java.util.ServiceLoader发现提供者的服务。

The service must be a class type, an interface type, or an annotation type. It is a compile-time error if a uses directive specifies an enum type (§8.9) as the service.

服务必须是类类型、接口类型或者注解类型。如果users指令指定了枚举类型(第8.9节)作为服务,则会产生编译时错误。

The service may be declared in the current module or in another module. If the service is not declared in the current module, then the service must be accessible to code in the current module (§6.6), or a compile-time error occurs.

服务可以在当前模块或者其他模块中声明。如果服务不是在当前模块中声明,那么该服务必须可以被当前模块中的代码访问,否则会产生编译时错误。

It is a compile-time error if more than one uses directive in a module declaration specifies the same service.

如果在一个模块声明中有多个uses指令指定了相同的服务,则会产生编译时错误。

7.7.4 Service Provision

7.7.4 服务提供

The provides directive specifies a service for which the with clause specifies one or more service providers to java.util.ServiceLoader.

provides指令将为with子句指定的一个或多个服务提供者指定一个服务给java.util.ServiceLoader。

The service must be a class type, an interface type, or an annotation type. It is a compile-time error if a provides directive specifies an enum type (§8.9) as the service.

服务必须是类类型、接口类型或者注解类型。如果provides指令指定枚举类型(第8.9节)作为服务,则会产生编译时错误。

The service may be declared in the current module or in another module. If the service is not declared in the current module, then the service must be accessible to code in the current module (§6.6), or a compile-time error occurs.

服务可以在当前模块或者其他模块中声明。如果服务没有在当前模块中声明,那么它必须可以被当前模块(第6.6节)中的代码访问,否则会产生编译时错误。

Every service provider must be a class type or an interface type, that is public, and that is top level or nested static, or a compile-time error occurs.

每个服务提供者必须是类类型或者接口类型,它是public的,并且是顶层级别或者是嵌套static的,否则会产生编译时错误。

Every service provider must be declared in the current module, or a compile-time error occurs.

每个服务提供者必须在当前模块中声明,否则会产生编译时错误。

If a service provider explicitly declares a public constructor with no formal parameters, or implicitly declares a public default constructor (§8.8.9), then that constructor is called the provider constructor.

如果服务提供者明确声明了一个没有形式参数的public构造函数,或者隐式声明了一个默认的public构造函数(第8.8.9节),那么这个构造函数就叫做提供者构造函数。

If a service provider explicitly declares a public static method called provider with no formal parameters, then that method is called the provider method.

如果服务提供者明确声明了一个名为provider而且没有形式参数的public static方法,那么这个方法就叫做提供者方法。

If a service provider has a provider method, then its return type must i) either be declared in the current module, or be declared in another module and be accessible to code in the current module; and ii) be a subtype of the service specified in the provides directive; or a compile-time error occurs.

如果服务提供者有提供者方法,那么它的返回类型必须:1)是在当前模块中或者其他模块中被声明,而且可以被当前模块中的代码访问;2)是在provides指令中指定的服务的子类型。否则会产生编译时错误。

While a service provider that is specified by a provides directive must be declared in the current module, its provider method may have a return type that is declared in another module. Also, note that when a service provider declares a provider method, the service provider itself need not be a subtype of the service.

虽然由provides指令指定的服务提供者必须在当前模块中声明,但是它的提供者方法可能具有在其他模块中声明的返回类型。另外注意,当服务提供者声明了提供者方法时,服务提供者本身不一定是服务的子类型。

If a service provider does not have a provider method, then that service provider must have a provider constructor and must be a subtype of the service specified in the provides directive, or a compile-time error occurs.

如果服务提供者没有提供者方法,那么该服务提供者必须有提供者构造函数以及必须有在provides指令中指定的服务的子类型,否则会产生编译时错误。

It is a compile-time error if more than one provides directive in a module declaration specifies the same service.

如果在模块声明中有多个provides指令指定相同的服务,则会产生编译时错误。

It is a compile-time error if the with clause of a given provides directive specifies the same service provider more than once.

如果给定的provides指令的with子句中多次指定了相同的服务提供者,则会产生编译时错误。

7.7.5 Unnamed Modules

7.7.5 未具名模块

An observable ordinary compilation unit that the host system does not associate with a named module (§7.3) is associated with an unnamed module.

主机系统不与具名模块(第7.3节)相关联的可观察的普通编译单元,是与未具名模块相关联的。

Unnamed modules are provided by the Java SE Platform in recognition of the fact that programs developed prior to Java SE 9 could not declare named modules. In addition, the reasons for the Java SE Platform providing unnamed packages (§7.4.2) are largely applicable to unnamed modules.

由于认识到在Java SE 9之前开发的程序无法声明具名模块,因此由Java SE平台提供了未具名模块。另外,Java SE平台提供了未具名包(第7.4.2节)的原因是为了适用于未具名模块。

An implementation of the Java SE Platform must support at least one unnamed module. An implementation may support more than one unnamed module, but is not required to do so. Which ordinary compilation units are associated with each unnamed module is determined by the host system.

Java SE平台的实现必须至少支持一个未具名模块。该实现可能支持多个未具名模块,但不需要这样做。由主机系统决定哪个普通编译单元与每个未具名模块的关联关系。

The host system may associate ordinary compilation units in a named package with an unnamed module.

主机系统可以将具名包中的普通编译单元与未具名模块相关联。

The rules for unnamed modules are designed to maximize their interoperation with named modules, as follows:

未具名模块的规则被设计为最大化与具名模块的互操作,如下所示:

• An unnamed module reads every observable module (§7.7.6).

• 未具名模块能够读取每个可观察模块(第7.7.6节)。

By virtue of the fact that an ordinary compilation unit associated with an unnamed module is observable, the associated unnamed module is observable. Thus, if the implementation of the Java SE Platform supports more than one unnamed module, every
unnamed module is observable; and each unnamed module reads every unnamed module including itself.

由于与未具名模块相关联的普通编译单元是可观察的,所以相关联的未具名模块是可观察的。因此,如果Java SE平台的实现支持多个未具名模块,则每个未具名模块都是可观察的; 并且每个未具名的模块能够读取每个未具名的模块,包括它本身。

However, it is important to realize that the ordinary compilation units of an unnamed module are never visible to a named module (§7.3) because no requires directive can arrange for a named module to read an unnamed module. The Core Reflection API of the Java SE Platform may be used to arrange for a named module to read an unnamed module at run time.

然而,重要的是要认识到未具名模块的普通编译单元永远不可见于具名模块(第7.3节),因为没有requires指令安排具名模块读取未具名模块。Java SE平台的核心反射API可用于在运行时安排具名模块读取未具名模块。

• An unnamed module exports every package whose ordinary compilation units are associated with that unnamed module.

• 未具名模块会导出与其相关联的普通编译单元的每一个包。

• An unnamed module opens every package whose ordinary compilation units are associated with that unnamed module.

• 未具名模块会开放与其相关联的普通编译单元的每一个包。

7.7.6 Observability of a Module

7.7.6 模块的可观察性

A module is observable if at least one of the following is true:

如果模块是可观察的,那么至少以下有一个是正确的:

• A modular compilation unit containing the declaration of the module is observable (§7.3).

• 包含模块声明的模块化编译单元是可观察的(第7.3节)。

• An ordinary compilation unit associated with the module is observable.

• 与模块相关联的普通编译单元是可观察的。

阅读全文
0 0
原创粉丝点击