More quiz questions available here
Imagine you are working on a new unit testing framework for Java classes and start with the following folder hierarchy:
src
└───com
└───acme
└───test
└───Test.java
There’s a single base Java class inside the project.
package com.acme.test;
// import statement(s) here if any
abstract sealed public class Test permits StaticTest, DynamicTest {
abstract public void test();
}
Which statements correctly describe the conditions when the code compiles successfully? Choose two.
A. | If you put the StaticTest and DynamicTest classes in the com.acme.test package, you do not need to provide module-info.java . |
|
B. | If you put the StaticTest and DynamicTest classes in the com.acme.test.util package, you do not need to provide module-info.java . |
|
C. | If you provide module-info.java , you must put the StaticTest and DynamicTest classes in the same module with the Test class. |
|
D. | If you provide module-info.java , you must put the StaticTest and DynamicTest classes in the com.acme.test package. |
|
E. | If all modules have a proper module-info.java file, you may put the StaticTest and DynamicTest classes in different modules. |
Answer. This question investigates some key restrictions of the sealed-type mechanism.
The sealed-type mechanism allows source code to make it very clear that only a specific set of subtypes are assignment-compatible with the sealed base type. Of course, it’s always been possible to limit the number of types that are assignment-compatible with a given type simply by not coding more classes than you want. But in that older approach, the design intent is not explicit in the code, and if others who are unfamiliar with your intentions work on the code, they might break this intention and create bugs by mistake.
Another benefit of sealed types is that if a naively made change adds a new assignment-compatible type, it causes a syntax error, alerting the programmer that the change should be discussed with others who are thoroughly familiar with the design.
A third benefit, which is expected to be realized fully when the final version of pattern matching for switch is released, is the ability to alert programmers to other areas of code that need to be updated if new assignment-compatible subtypes are added by the proper syntactic mechanism. (Specifically, the switch statement will be able to issue an error if the new type is omitted from the set of patterns mentioned in case clauses.)
In pursuit of these goals, Java 17’s JEP 409 (sealed classes) makes the following comment:
The classes specified by permits
must be located near the superclass: either in the same module (if the superclass is in a named module) or in the same package (if the superclass is in the unnamed module).
Notice this enumerates two possibilities.
It’s worth noting that the Java compiler determines whether code is intended for use in the module system by determining the presence or absence of a module-info.java
file. This is somewhat approximate, since code can be compiled into a module but then be executed from the unnamed module if the JAR file containing the code is located on the classpath during execution.
From the rules listed in JEP 409, you know that it’s mandatory that all elements of the sealed hierarchy be in the same package if the code is not running in a named module. This makes option A correct.
You also know that it’s permissible to place members of the sealed hierarchy in different packages only if the code is running in a named module. Since the compiler approximates this determination based on the presence or absence of a module-info.java
file, option B is incorrect.
Option C is also correct because, as mentioned above, permitted types must be as close as possible to sealed types, and the most permissive interpretation is that all the types must be in the same module. One factor here is that modules are commonly developed and compiled independently, which means it’d be much harder to keep track of the total hierarchy if this rule did not exist.
Option D is incorrect. It is not mandatory to put all the permitted types into the same package when you build a sealed-type hierarchy with a module-info.java
file, which the compiler interprets as building a module (even if the code might not be run in that way).
Option E is also incorrect, because you can never spread a sealed type and its permitted types across different modules.
Conclusion. The correct answers are options A and C.
Simon Roberts joined Sun Microsystems in time to teach Sun’s first Java classes in the UK. He created the Sun Certified Java Programmer and Sun Certified Java Developer exams. He wrote several Java certification guides and is currently a freelance educator who publishes recorded and live video training through Pearson InformIT (available direct and through the O’Reilly Safari Books Online service). He remains involved with Oracle’s Java certification projects.
Mikalai Zaikin is a lead Java developer at IBA Lithuania (part of worldwide IBA Group) and currently located in Vilnius. During his career, Zaikin has helped Oracle with development of Java certification exams, and he has been a technical reviewer of several Java certification books, including three editions of the famous Sun Certified Programmer for Java study guides by Kathy Sierra and Bert Bates.
Previous Post
Next Post