Monday, January 1, 2024
Quiz yourself: Serializing a primitive with ObjectOutputStream
Monday, December 4, 2023
Quiz yourself: Read and write objects by using serialization
Test your knowledge of the java.io.Serializable interface.
- First, the Order class implements the Serializable marker interface. Presumably this is a result of the partial refactoring work already performed.
- Second, the Order class has two fields. One is an int and the other is an ArrayList. Neither is marked transient, and both are serializable members of core Java.
- Third, the list contains Item objects, but the Item class does not implement the Serializable interface. You are prohibited from altering the source code of the Item class and from subclassing the class, since it is final.
Friday, September 29, 2023
Quiz yourself: Deserializing objects that have a nonserializable parent
What’s correct and what’s not correct about the Java deserialization process?
- When a serializable object is deserialized, the nonserializable parent aspects are initialized by calling an accessible zero-argument constructor in the immediate parent that’s not serializable.
- Except for record types, deserialization does not use any of the constructor or initialization code for the elements of that object hierarchy that are serializable.
Wednesday, September 27, 2023
Quiz yourself: Serializing a primitive with ObjectOutputStream
Primitives? Objects? What should you do?
Friday, September 15, 2023
Quiz yourself: Deserializing objects with readObject
Friday, September 8, 2023
Quiz yourself: Collectors, comparators, and type inferencing in Java
Thursday, August 31, 2023
Quiz yourself: Try-with-resources and PreparedStatement database access
The best uses—and some limitations—of try-with-resources
Which of the following will work correctly with the new SELECT statement while ensuring that the database resources are handled properly? Choose one.
Friday, August 25, 2023
Quiz yourself: The overloaded submit(…) methods in Java’s ExecutorService
Know when to use Runnable and Callable in multithreaded code.
- <T> Future<T> submit(Callable<T> task);
- Future<?> submit(Runnable task);
- <T> Future<T> submit(Runnable task, T result);
- A Callable returns a value, whereas the Runnable declares a void method.
- A Callable may throw a checked exception, but a Runnable can throw only an unchecked exception.
Wednesday, August 16, 2023
Quiz yourself: Using anonymous classes in Java
How are anonymous classes related to the Liskov substitution principle?
Friday, August 11, 2023
Quiz yourself: Abstract classes and the difference between Java’s super() and this()
Wednesday, August 2, 2023
Quiz yourself: How Java resolves access to static elements in a type declaration
Oh no! The situation seems to be complicated for several reasons.
Wednesday, July 26, 2023
Quiz yourself: Java’s sealed types—true-or-false quiz
Test your knowledge of valid sealed classes, subclasses, and the permits section.
Which statement is true? Choose one.
A. A sealed type declaration must have a permits section.
B. A sealed class must have at least one direct subclass.
C. A sealed interface must have at least one direct implementation.
D. A sealed type can be an enum.
E. A sealed type can be a record.
Answer. The goal of a sealed type hierarchy is to have source-level specifications that make it very clear what types are permitted to be assignment-compatible with a given base type.
Clearly, even if you don’t have a sealed type hierarchy, you can find this information if you search all the source files used in your codebase. However, that’s laborious at best, and it’s impractical if you have libraries that came from other teams—or from third parties.
As a broad overview, the sealed type mechanism allows the source for one type to explicitly enumerate all its permitted subtypes. Each of those subtypes in turn is subject to restrictions that are generally intended to keep the entire tree clearly visible from the source code.
One possibility is that a subtype is final (either explicitly or implicitly, which is the case with a record type). In this case, you’ve reached the end of the type hierarchy on this branch of the tree.
Another possibility is to open up the hierarchy and allow arbitrary subtypes. This, to an extent, spoils the point of a sealed hierarchy, but it is permitted because practical considerations might warrant it. This is achieved by marking the type as non-sealed.
A third possibility is that the subtype is an enum. An enum can never be named in an extends clause, which means that the sealed parent type must be an interface. Also, subtypes of an enum can exist only when they are declared as inner classes. As inner classes, they’re in the source code of the enum itself, which makes it very clear what, if any, subtypes exist under this branch of the type tree.
The final option is for the subtype itself to be marked as sealed. In this case, its children can be expressly listed. Also in this case, the subtypes’ children are subject to these rules. Once again, it’s very clear from the source which subtypes are possible.
While it’s usual for a sealed type to enumerate its permitted children with permits, there is one situation in which this can be omitted (note that permits is mandatory otherwise). That situation is when all the child types are declared in the same source file (or compilation unit) as the parent type. This includes the possibility of those types being inner or nested classes within the parent type.
This last possibility tells you that option A is incorrect.
The description above omitted an important detail: The purpose of a sealed type hierarchy is to enumerate clearly the permitted child types. If you want zero children of a given type, that class should be marked as final (and, of course, it must be a concrete class). A sealed type must have at least one subtype. This tells you that option B is correct.
Option C is incorrect. Any sealed type must have some child type, but it’s not necessary for an interface to have a direct implementation; it’s perfectly acceptable for it to have a subinterface. Note that an interface cannot be marked as final, so a subinterface of a sealed interface must be either sealed or non-sealed to be valid.
Although an enum cannot be marked as final, a subtype of an enum must be an inner class. This already makes for tight control of the types that can ever be assignment-compatible with it. Of course, this is why an enum can be declared on a sealed type hierarchy without being labeled either sealed, non-sealed, or final. As noted earlier, the sealed parent type of an enum must be an interface. It’s not useful—and is, in fact, not permitted—for an enum type to be marked as sealed. Hence, option D is incorrect.
Record types are implicitly final; hence, they cannot permit subtypes. You know from the discussion related to option B that at least one subclass is mandatory, so you can deduce that option E is also incorrect.
Don’t forget that it’s entirely correct for a record type to appear in a sealed type hierarchy; it simply must be a leaf node, not the root of the hierarchy. It’s also worth observing that since a record type cannot declare a parent class, all the parent types of a record in a sealed hierarchy, up to and including the root of that hierarchy, must be interfaces.
Conclusion. The correct answer is option B.
Source: oracle.com
Monday, July 24, 2023
Quiz yourself: Comparing Java arrays and interpreting the mismatch method
The java.util.Arrays class methods aren’t always intuitive.
Given the following code fragment
int a1[] = { 5, 24, 54, 22 };
int a2[] = { 5, 23, 56, 202 };
int a3[] = { 3, 8, 19, 39, 56 };
System.out.print(Arrays.compare(a1, a2));
System.out.print(Arrays.compare(a3, a2));
System.out.print(Arrays.mismatch(a1, a1));
System.out.print(Arrays.mismatch(a2, a1));
Which output is guaranteed? Choose one.
A. 1-1-11
B. 2-1-12
C. 11-11
D. 2-202
E. None of the above
Answer. This question explores the Java API for the java.util.Arrays class, specifically the compare() and mismatch() methods.
The compare() method compares two arrays lexicographically. That’s a fancy way of saying it compares them in the same way that textual words are ordered in a dictionary. Importantly, that’s not the same way numbers are ordered.
Notice that for words such as Hello and Goodbye, a dictionary will order Goodbye before Hello, because G comes before H in the alphabet. Even though there are more letters in Goodbye, the first difference determines the ordering.
Contrast this with numbers; for example, 90,000 would come before 5,000,000 even though the digit 5 is less than the digit 9. The ordering imposed by Arrays.compare works this way, even when comparing arrays of numbers.
In addition, Arrays.compare checks corresponding pairs of elements at the same positions, starting at index position 0 and checking increasing index positions. As long as pairs of elements compare as equal at the same subscript, it keeps checking. If the comparison process reaches the end of both arrays simultaneously, which can happen only if no differences have been discovered, the arrays are deemed to be equal. If the comparison process reaches the end of one array before the other, but the two are identical up to the end of the shorter array, the longer array is considered to be larger.
By the way, a null array reference is considered to be smaller than any non-null array. Two null array references are considered to be equal.
In the case of this question, the elements of arrays a1 and a2 differ at index 1. At that position, the value in a1 (24) is larger than that in array a2 (23), which makes array a1 larger than array a2.
For the comparison of array a3 with array a2 (note that a3 is the first of the two arguments), the arrays differ at index 0, with array a3 being the smaller.
So, what is the result of the Arrays.compare method when the arrays have differing values at an index, as in this case? To determine that, you must go on a bit of a treasure hunt. The documentation for Arrays.compare(int[], int[]) states the following:
...the lexicographic comparison is the result of comparing two elements, as if by Integer.compare(int, int).
That leads to the documentation for Integer.compare(int, int) which states
Compares two int values numerically. The value returned is identical to what would be returned by: Integer.valueOf(x).compareTo(Integer.valueOf(y))
By following the trail, you’ll see that the documentation of Integer.compareTo(Integer) states that the result will be
...the value 0 if this Integer is equal to the argument Integer; a value less than 0 if this Integer is numerically less than the argument Integer; and a value greater than 0 if this Integer is numerically greater than the argument Integer (signed comparison).
It’s worth noting that this is consistent with the documentation for the compare method in the Comparator interface.
If you create the code for this question and try it, you’ll (almost certainly) find that the output of the comparisons is actually 1, followed by -1, which would make option A look likely to be correct (although the output from the second pair of methods has not been considered yet). But the documentation doesn’t say that the method will return 1, 0, or -1. Rather, it merely says the result will be positive, zero, or negative.
Consequently, you can’t state that the correct answer is A. Rather, the correct answer must be option E.
Although you now know the correct answer, these questions are, of course, intended for learning, rather than for merely seeing if you get the answer right or wrong. So, it’s worth investigating the behavior of the mismatch() method.
The mismatch() method returns the index value of the first point in the arrays where the values of the elements differ. If the arrays are identical in contents and length, the method returns -1. Also, if either array reference is null, a NullPointerException is thrown. (Keep in mind that Java array indexes are zero-based.)
Given these rules, the output of the mismatch operation with both arguments provided as in array a1 must be -1. The output of the mismatch operation with the arguments for array a2 and array a1 will be 1, because the index contains the values 23 and 24. This is consistent with option A.
So, if you run the code, the output will almost certainly match option A, and this would be correct if the question were phrased as “Which output is possible?” However, as noted, a valid JDK or JRE could have a library implementation that returns values other than +1 and -1 from the compare method.
We hope you won’t hate us for this question; precision and avoidance of unsound assumptions can be important in day-to-day programming as well as during exam taking!
Conclusion. The correct answer is option E.
Source: oracle.com












