Chapter 1. Understanding Modules

1.1.  Describe the Modular JDK

Question 010101

Given the code fragment:

try (
    Connection conn = DriverManager.getConnection(...);
    Statement stmt = conn.createStatement();) {
    // ...
}
					
					

Which two actions when done simultaneously will allow the code compile successfully?

Options (choose 2):

  1. Add to the class definition: import java.sql.*;

  2. Add to the class definition: requires java.sql.*;

  3. Add to the module definition: requires java.base;

  4. Add to the module definition: requires java.se;

  5. Add to the module definition: open java.sql;

Answer:

The correct options are 1 and 4.

As of Java SE 9 all standard Java API packages are placed into modules -- JDK became modular.

Standard Java SE modules start with java. prefix, ideally your application should "require" only java.* modules.

The non-standard JDK modules start with jdk. prefix, they  include debugging and serviceability tools and APIs, development tools, and various service providers, which are made available to other modules via the existing java.util.ServiceLoader mechanism.

Option 1 is correct, even if you "require" a correct Java SE module, you still need to import the package (or individual classes) in order to use short form of class name (Connection v.s. java.sql.Connection). NOTE: two packages are always implicitly imported in Java applications: current package where the class is located, and java.lang package (which contains such common classes as String, Object, System, etc..).

Option 2 is wrong, you need to use "import" keyword in order to import package/class.

Option 3 is wrong. The java.base standard Java SE module indeed contains some common packages (e.g. java.io, java.lang, java.nio, java.util, java.time, and many more), but the JDBC classes are placed into own java.sql module.

Option 4 is correct. Java SE has a special aggregator module named java.se, which does not contain any own package, rather "requires transitive" all standard java.* modules. The "transitive" modifier means that what "required" in java.se (i.e. all standard Java SE modules) will be required to client code as soon as client module definition has "requires java.se;"

Another approach to compile the code would be to require specifically the SQL module: requires java.sql;

Option 5 is wrong: A module is allowed to open only own packages. It does not make sense and violates encapsulation to open a package from some third-party module. And the open directive will not provide visibility of JDBC classes to the application.

Source:

Understanding Java 9 Modules [https://www.oracle.com/corporate/features/understanding-java-9-modules.html]

Question 010102

You are writing a modular application for Java 11 platform which uses SAX XML parser.

From JavaDoc you know that the javax.xml.parsers.SAXParser parser class belongs to java.xml module.

Which step you must do in order to use this class in your application?

Options (choose 1):

  1. Add the option to java and javac: -p java.xml

  2. Add the option to java and javac: -cp java.xml.mod

  3. Add directive to the module definition: requires java.xml;

  4. Add directive to the module definition: requires java.base;

Answer:

The correct option is 3.

Option 1 is wrong. It does not cause error, but it is useless and does not make sense. The -p is a short form of --module-path option, which defines location where modules are looked up when creating a module graph during compile time or runtime.

Standard Java SE modules start with java. prefix (e.g. java.xml) and they are avalable by design, without need to add them to module path.

Option 2 is wrong. It does not cause error, but it is useless. The -cp is a short form of --class-path (or -classpath) option, which defines location where classes are looked up when classloader needs to load a class to JVM.

There is a problem with this option for several reasons:

  • Standard Java modules are available by design without adding to classpath or module path.

  • Modules are added to modulepath.

  • To classpath you can add .jar files or directories

  • When something added and loaded later via classpath it becomes part of unnamed module in Java 9 and higher, the unnamed module cannot be accessed from a named module (the opposite direction access is possible).

Option 3 is correct. When we define some module as "required" in module definition, it will be added to modules graph at compile time or runtime, and classes/interfaces from this module can be seen by JVM classloader.

Option 4 is wrong. The java.base module always implicitly added in modular applications, even if you do not "require" it. But java.base contains only some common packages (e.g. java.lang). The XML parsing classes/interfaces are stored in a separate module (java.xml) which must be direcly or indirectly "required".

A possible option which would work can be requiring Java SE aggregator module in module definition: requires java.se;

Source:

Understanding Java 9 Modules [https://www.oracle.com/corporate/features/understanding-java-9-modules.html]

Question 010103

While compiling your modular application you got the error from javac:

import java.sql.Connection;
           ^
  (package java.sql is declared in module java.sql, but module modS does not read it)
1 error					
					

Which two changes when done independently will resolve this error?

Options (choose 2):

  1. Run javac with option: --module-path java.sql

  2. Run javac with option: -modulepath java.sql

  3. Run javac with option: -mp java.sql

  4. Add directive to the module definition: requires java.sql;

  5. Add directive to the module definition: requires transitive java.sql;

Answer:

The correct options are 4 and 5.

Option 1 is wrong. It does not cause error, but it is useless and does not make sense. The --module-path option defines location where modules are looked up when creating a module graph during compile time or runtime.

Standard Java SE modules start with java. prefix (e.g. java.sql) and they are avalable by design, without need to add them to module path.

Options 2 and 3 are wrong. These are invalid options (flags) for javac compiler. You need to remember common options for java and javac.

Option 4 is correct. When we define some module as "required" in moodule definition, it will be added to modules graph at compile time or runtime, and classes/interfaces from this module can be seen by JVM classloader.

The requires directive specifies the name of a module (i.e. java.sql) on which the current module has a dependence.

Option 5 is correct. It is similar to option 4 above, but with some "enhancement".

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. In other words, when some other module "requires" our application module, it will implicitly "require" java.sql module and will not need to require it explicitly via separate requires java.sql; directive.

Source:

Understanding Java 9 Modules [https://www.oracle.com/corporate/features/understanding-java-9-modules.html]

JLS 11. Section 7.7.1. Dependences [https://docs.oracle.com/javase/specs/jls/se11/html/jls-7.html#jls-7.7.1]

Professional hosting         Exam 1Z0-817: Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer Study Guide     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz