These are the first activities linked to the chapter drafts. Each task states what to observe; the solutions are reasoned examples to compare with your own attempt. All code on the main path uses Java 25 without preview features. To compile the source files and check the outputs in a clean environment, you can run verify-first-six.py from the project root.
C01-A01 – Choosing a Path and Checking the Environment
Task. Write three sentences stating what you already know about programming, which section of the book you will read first, and what result will tell you that you have understood the chapter. Then run java --version and javac --version and keep both outputs together with the date. Do not include personal paths or confidential data in your submission.
Criterion. The chosen path must be compatible with the stated prerequisites. Both commands must be available and show a consistent JDK version. The activity does not grade your starting knowledge: it helps you choose where to begin.
Hints. If you cannot choose, start with chapters C02 and C03 and postpone the further reading boxes. If a command is not found, distinguish a missing JDK from an unconfigured executable path. If the versions differ, check which installation the terminal finds first.
Commented solution. One possible answer is: “I know variables and loops, but I have never used Java. I read C02–C05 in order and try every complete program. I consider C03 understood when I can explain why javac and java are different commands.” The outputs depend on the computer, so there is no string to copy. The observable evidence is being able to repeat both commands and explain that the second checks the compiler.
C01-G01 – Using the Book's Conventions
Task. Open the section on conventions and choose a complete program, a code fragment, a note, and a further reading section in chapters C02–C06. For each, write which action is required of you: compile it, place it in context, use it to avoid a mistake, or postpone it until after the main path. Also explain where you would look for a complete program's source file.
Criterion. The answer distinguishes a runnable program from a fragment and does not treat notes and further reading sections as instructions to copy into the terminal. The complete source file is found in the chapter's materials.
Hints. Look for a block declaring public class and one showing only a few lines. Read the paragraph before and after each block.
Commented solution. A complete program is saved in the stated file and checked with the given commands; a fragment requires the context of a class or method. A note points out a concrete risk, while a further reading section adds a detail that can be read after the main path. The files in examples are the compilable versions of the complete programs.
C02-A01 – Recognizing Responsibilities and Relationships
Task. A reader borrows a book. State which object you would record the loan date in and why. Then explain in words the difference between “Library is a Collection” and “Library has a collection.” No code is needed.
Criterion and feedback. The answer must connect the date to the loan event and distinguish inheritance from composition. If the date ends up only in Book, ask yourself how you would represent two loans of the same book at different times. If you use “is a” merely to reuse methods, reread the paragraph on responsibilities.
Commented solution. Loan connects a book to a reader over a time interval; therefore, it knows the starting date. Saying “Library has a collection” describes part of its state, while “Library is a Collection” assigns the type and contract of a collection to the library. The second statement requires stronger justification than simple reuse.
C02-P01 – Modeling a Library
Task. Starting with a reader who requests a book and returns it, propose at least three program entities. For each, state a responsibility, a piece of data it knows, and an operation it performs. Draw the relationships between the entities. Then evaluate the statement “The library extends the collection of books so that it reuses the collection's methods.”
Criterion. The model must distinguish Book, Reader, and Loan; an inheritance relationship must truly mean “is a.” A rule must prevent an impossible state, such as two returns of the same loan without an explicit decision. The reasoning matters more than a single hierarchy.
Hints. Ask which event a return date belongs to. Try reading the relationships aloud as sentences. If “Library is a Collection” seems forced, consider “Library has a collection.”
Commented solution. Book knows the title and author; Reader identifies who borrows; Loan connects the two and knows the start and any return. The library coordinates searching and recording and has a collection of books. The inheritance proposed in the task confuses code reuse with conceptual membership. A human check applies the rubric in the activity plan: correctness, reasoning, model quality, and robustness of the rules.
C02-D01 – A Hierarchy Built to Reuse Code
Task. A project proposes Loan extends Book because both have a date, and Library extends ArrayList<Book> because the library stores books. Identify the two conceptually weak relationships and rewrite them in prose without using inheritance where there is no “is a” relationship.
Criterion. The diagnosis distinguishes the loan from the book and the library from the collection it uses. Saying that extends is syntactically possible is not enough: you must explain what promises it would make to callers.
Hints. Read “a loan is a book” and “a library is a list” aloud. Ask where the return date belongs.
Commented solution. Loan connects book and reader and knows the operation's dates; it has a reference to the book. Library coordinates a catalog and has a collection, but should not automatically expose every ArrayList operation. Composition makes the two contracts clearer.
C03-A01 – Source, Class, Execution
Task. Put Greeting.java, javac, Greeting.class, java, and the JVM into working order. Then explain why changing only the .java file does not modify the already compiled program's output.
Criterion and feedback. The explanation must distinguish the source file from the compiled file, and the compiler from the startup program. If you attribute production of the .class to java in the chapter's example, retrace the two commands printed in C03.
Commented solution. javac reads Greeting.java and produces Greeting.class; the java command starts the JVM, which loads the class and executes its main method. A source modification affects that file, but does not rewrite the existing .class by itself.
C03-G01 – Compile, Observe, Diagnose
Task. Enter the folder containing Greeting.java and Arguments.java, then compile the former with javac --release 25 -d build Greeting.java. Start it with java -cp build Greeting and observe the class structure with javap -classpath build Greeting. Modify only the sentence in the source and run again without recompiling; finally recompile and retry. Also compile Arguments.java with javac --release 25 -d build Arguments.java and run java -cp build Arguments first. Explain which parts of the command line are java command options and which part is the program's argument.
Criterion. The output after the first compilation is Hello, Java 25!. javap shows the main method. Modifying only the .java does not change the behavior of the already produced .class; recompilation updates it. The second program prints First argument: first. Record commands, JDK version, and exit codes.
Hints. If java cannot find the class, check the folder passed to -cp. If javac cannot find the source, check the folder from which you run the command. If you modify a keyword and the compiler fails, you are still in compilation: the JVM has not executed the new program.
Commented solution. javac reads text and produces build/Greeting.class; java reads the compiled file in the specified folder. That is why a source change becomes observable only after another compilation. javap does not reconstruct the original text, but shows the compiled class's structure and makes main's presence visible. In the second execution, -cp build is a java option, Arguments is the class name to start, and first is the text delivered to its main method.
C03-D01 – A Compiled File That Cannot Be Found
Task. In a clean folder, compile Greeting.java with javac --release 25 -d build Greeting.java. If you run java -cp . Greeting from the folder containing only the source and build/, the program cannot find the class. Explain why, and correct the command without recompiling.
Criterion. The answer indicates that Greeting.class is in build/ and uses java -cp build Greeting. It does not attribute the error to the contents of main.
Hints. Observe the effect of -d build and the role of -cp in the startup command.
Commented solution. javac produced build/Greeting.class; -cp . searches for the class in the current folder rather than inside build/. java -cp build Greeting indicates where to find the already compiled class. There is no need to change the source.
C04-A01 – Predicting Type and Index
Task. Without running code, indicate the first valid index of int[] grades = {20, 25, 30};, the value of grades.length, and the type of the expression a + b when a and b are byte variables. Explain in one sentence why var does not make a local variable's type dynamic.
Criterion and feedback. The three answers are 0, 3, and int. If you confuse length with last index, draw three cells and write 0, 1, 2 above them. If you think var allows a subsequent type change, reread the distinction between inferred and actual type.
Commented solution. Array indexes start at zero, so the third cell has index 2 even though there are three elements. In addition, both byte values are promoted to int. With var, the compiler derives a type from the initializer; that type remains the variable's type throughout its lifetime.
C04-P01 – Four Grades and a Conversion
Task. Modify GradeAverage.java using {20, 25, 28, 30} and calculate the average. Before running, predict the result. Then explain what would change if (double) were removed and why byte c = a + b; might not compile even when a and b are small. Finally, run NumericConversions.java and compare its output with your prediction.
Criterion. The average is 25.75; the sum includes four elements. The explanation distinguishes integer division, explicit conversion, and promotion of byte to int. Observed values in NumericConversions are compared with those expected in the chapter.
Hints. First sum the four numbers on paper. Check the type of /'s left operand. Remember that the compiler decides the type of a + b using expression rules, rather than the size of values in one particular execution.
Commented solution. 20 + 25 + 28 + 30 equals 103; 103 / 4.0 equals 25.75. Without the cast, 103 / 4 produces the integer 25, which is then converted to 25.0 if assigned to a double. An arithmetic expression with two byte values is promoted to int, so direct assignment to byte requires a check or conversion, which may lose information. In the conversions program, Long.MAX_VALUE narrowed to int becomes -1; widening Integer.MAX_VALUE to long preserves the value.
C04-D01 – An Index Beyond the Last Element
Task. Evaluate the fragment int[] grades = {20, 25, 30}; for (int i = 0; i <= grades.length; i++) System.out.println(grades[i]);. Indicate the lines appearing before the error, the first invalid index, and the minimal correction to the loop condition.
Criterion. 20, 25, and 30 are printed; access with index 3 fails during execution. The condition becomes i < grades.length.
Hints. Write indexes beneath the three elements. The value of length counts cells but is not a valid index in this array.
Commented solution. Valid indexes are 0, 1, and 2. With <=, the loop also tries i == 3; the array has no such cell, and Java throws ArrayIndexOutOfBoundsException. With <, the loop stops after the last element.
C04-P02 – Representation, Type, and Copying
Task. Before running BitsStepByStep.java, predict the results of 100 >> 1, 100 ^ 125, ~100, and -8 >>> 1. Indicate which results can be understood by observing only the final eight bits and which require remembering that the type is int. Then create int[] first = {24, 27}; int[] second = first;, assign 30 to second[0], and predict first[0]'s value. Repeat after obtaining second with first.clone().
Criterion and feedback. The four values are 50, 25, -101, and 2_147_483_644; ~ and >>> on the negative value require the complete int representation. In the first case, both names designate the same array and first[0] becomes 30; after copying, it remains 24.
Commented solution. The right shift of 100 produces 50; XOR retains differing bits of 100 and 125, yielding 25. ~ inverts all 32 bits and >>> inserts zeros on the left, so the eight bits drawn on paper are insufficient for those two results. Assigning one reference to another does not copy elements; here, clone() creates a new primitive-value array independent of the first.
C05-A01 – Choice or Repetition?
Task. Choose a control structure for each case and explain the choice: assign a label to a number from 1 to 7; keep requesting data until it is valid; visit each grade in an array. For the first case, also indicate where you would put the value to use when the number is outside the range.
Criterion and feedback. There must be a choice with default, a loop, and an array traversal. If you use if for each grade already known in the array, ask which part of the code would change when there are one hundred grades.
Commented solution. A switch expression makes the seven cases visible, and a default covers other integers. A while repeats the request while the condition remains true; define the condition so the loop can terminate. Enhanced for visits grades when the index is not needed.
C05-G01 – From Choices to Loops
Task. Run GradeAverageWithLoop.java with the three initial grades {24, 27, 30}, then with {20, 25, 28, 30}, and finally with an empty array. Modify the array in the source and recompile between experiments; before running, predict every output. Then observe InitialDraughts.java: explain why it produces twelve pieces per color and which two board rows remain empty. Finally, rewrite a weekday/weekend classification with a switch expression, using cases 1–7 and a default for other integers.
Criterion. No empty case causes division; the average does not depend on the length fixed in the source; the switch produces a value for every integer; the board counts twelve white and twelve black pieces.
Hints. The empty-array guard must precede division. Enhanced for visits each value without an explicit index. In draughts, a row has four cells for which (row + column) % 2 == 1.
Commented solution. The three initial grades produce Average: 27.0; the four grades produce Average: 25.75. With int[] grades = {};, the program prints No grades available and ends the method before division. Draughts fills rows 0–2 and 5–7; rows 3 and 4 remain empty. The switch can use case 6, 7 -> "weekend"; case 1, 2, 3, 4, 5 -> "weekday"; default -> "invalid value";, as explained in the text.
C05-G02 – The Eleven Cases and Boundaries
Task. Run IntegerAsStringCompared.java with 0, 3, 10, -1, and 11, first recording a prediction of both lines for each input. Then try starting it without arguments. Add case 11 to both forms and explain why the final branch remains necessary.
Criterion and feedback. The if and switch versions agree for all five values; without arguments, the usage instruction appears. After the addition, 11 has an explicit word, but -1 and 12 remain out of range. If the negative-number experiment still prints “greater than ten,” the message does not describe the correct domain.
Commented solution. The first three values produce zero, three, and ten in both versions; -1 and 11 produce out of range. The args.length guard avoids accessing args[0] when the argument is absent. Adding 11 makes the case part of the domain, but a program receiving an int can still receive many other values: the final branch keeps boundary behavior defined.
C05-P01 – Patterns, Records, and Dominated Cases (Advanced)
Task. Start with OutcomesWithPatterns.java. Before running it, write the expected output for a grade 27, a grade 15, a suspended outcome, and null. Then reverse the two Valid cases and observe the compiler message. Explain why one case can no longer be reached. Restore the correct order and check compilation without preview.
Criterion. All four branches are exercised; the guarded case precedes the general one; the switch is exhaustive over the sealed hierarchy and handles null explicitly. The introduced error is described as dominance, rather than a JVM defect.
Hints. Read Valid(int grade) as extraction of the field from the record. Ask whether a Valid with grade 27 also matches the unguarded pattern. A case catching every value of the next must appear afterwards.
Commented solution. The output is passed: 27, to retake: 15, suspended: missing documents, absent. If case Valid(int grade) comes first, it also includes values for which grade >= 18 and eliminates the more specific case's role. The compiler detects this dominance. The material remains labeled advanced because records and sealed hierarchies are developed in subsequent chapters; here we care about control flow.
C05-D01 – A continue That Does Not Advance the Loop
Task. Without running the fragment int i = 0; while (i < 3) { if (i == 1) continue; i++; }, follow three loop steps. Explain why it does not terminate and rewrite it so i reaches 3 even when it skips the rest of the body.
Criterion. The answer identifies i == 1 as a fixed point: continue restarts the while before i++. One correction moves the increment before the branch or uses a for whose update occurs after continue.
Hints. Record i at the start of each iteration. Ask which statement is skipped when the branch is true.
Commented solution. After the first iteration, i equals 1. In the next, continue skips i++, so the condition remains true and the value does not change. Writing i++; if (i == 1) continue; in the body eliminates that fixed point; in a real program, also check that the other operations' order remains as intended.
C06-A01 – Three Names, Three Functions
Task. Explain what changes when moving Catalog to another package, adding an import for ArrayList, and having a module declare exports for the package containing a public class. Indicate which operation abbreviates a name in the source.
Criterion and feedback. Answers must distinguish class identity, writing the reference, and accessibility between modules. If you answer that import moves ArrayList, compare its qualified name before and after the import: it remains java.util.ArrayList.
Commented solution. Changing Catalog's package changes its qualified name and requires updating the declaration, folders, and startup commands. Importing ArrayList allows writing only ArrayList in the file declaring the import; the class remains in java.util. exports allows modules reading the catalog module to access public types in the exported package.
C06-G01 – Two Modules and a Service
Task. Compile the sources in examples/C06/service from the root of javamattone/english with javac --release 25 --module-source-path examples/C06/service/src -d build/mods -m javabricks.catalog,javabricks.app. Start with java --module-path build/mods -m javabricks.app/javabricks.app.Main. Read both module-info.java files and indicate who uses the service, who provides it, and which package is exported. For diagnosis, temporarily remove exports, then requires, and compare the two compilation errors. Restore the files afterwards.
Criterion. The positive output is Hello from the catalog module. The application declares requires and uses; the catalog declares exports and provides. The implementation's package remains internal. The two introduced errors must be explained as lack of accessibility and readability, respectively.
Hints. import abbreviates a name in the source: it does not replace requires and exports. ServiceLoader searches for an implementation declared to the module system. If startup fails, check that both module folders are under the path passed to --module-path.
Commented solution. The javabricks.app module reads javabricks.catalog and uses the Greeting interface. The catalog module exports javabricks.catalog.api and provides EnglishGreeting, which belongs to a non-exported package. ServiceLoader obtains the service without the application naming the concrete class. Removing exports prevents the other module from using the public interface; removing requires prevents the calling module from reading the module containing it. There is no need to open the internal package with opens for this example: provides declares the necessary relationship.
C06-C01 – Deciding a Catalog's Boundary
Task. Design two modules: one offers a book catalog, the other uses it. The catalog has an api package with a public interface and an internal package with the implementation. Describe in words which packages to export and which module must declare requires. Explain the choice from the catalog user's perspective.
Criterion. The catalog module exports only the API package; the calling module declares that it reads the catalog. The internal implementation does not accidentally become public. The answer distinguishes Java type visibility from accessibility across the module boundary.
Hints. Start from the code the caller must write and identify the type it names. An internal package can remain accessible to its own module's components without being exported.
Commented solution. In the catalog's module-info.java, declare exports catalog.api;; in the application's module, requires catalog;. The implementation class in catalog.internal remains hidden from other modules. If the program wants to load it as a service, add uses and provides with an explicit contract, as in the guided example.
C06-D01 – The Wrong Path at Startup
Task. You compiled the guided program's modules into build/mods. A colleague tries java -cp build/mods javabricks.app.Main and receives a class-not-found error. Explain why the command does not reflect the compiled structure and write the correct startup command.
Criterion. The answer uses --module-path build/mods and -m javabricks.app/javabricks.app.Main. It distinguishes the class path, which searches for classes, from the module path, which presents named modules to the system.
Hints. Look at folders produced by -d during modular compilation and read the module-info.java of the module to start.
Commented solution. build/mods contains compiled module directories, rather than the class directly in the path the -cp command searches. Startup is java --module-path build/mods -m javabricks.app/javabricks.app.Main: it identifies the module path and module with its main class.