Friday, September 15, 2023

Quiz yourself: Deserializing objects with readObject

Quiz Yourself, Oracle Java Career, Oracle Java Skill, Oracle Java Jobs, Oracle Java Prep, Oracle Java Preparation, Oracle Java Object

You should know how the readObject method works—and when it won’t compile.

Given the following Person record

record Person(String name) implements Serializable {}

and the following method fragment

try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {
    ... // code here
    System.out.println(person.name());
}

Assume that the try block is completed with necessary catch blocks and the file contains a serialized Person and opens correctly.

The code from which option, when placed where the comment is, properly deserializes the object and allows the rest of the code to work? Choose one.

A. var person = (Person) null;
if (in.readObject() instanceof Person p) {
  person = p;
}
B. var person = in.readObject();

C. Person person = null;
if (in.readObject() instanceof Person) {
  person = in.readObject();
}

D. var person = null;
Object o = in.readObject();
if (o instanceof Person) {
  person = (Person) o;
}

Answer. We will skip over option A for the moment.

Option B would read the serialized object from the file, but the return type of the readObject method is declared as Object; therefore, var will infer the type of the person variable to be Object too. This means that person.name() will not compile. From this you can see that option B is incorrect.

Option C is incorrect for two reasons. The semantics of the code would cause the input stream to be read twice, and the result of the first reading operation would be lost. However, there is a more severe problem; as already mentioned, the return type of readObject is Object, and the following assignment to the person variable (which is declared explicitly as being of type Person in this option) would fail unless an explicit cast were added:

person = in.readObject(); // assignment fails!

The following cast would fix the problem:

person = (Person)in.readObject(); // this could work

Option D is also incorrect. When var is used to declare a local variable (other than a lambda formal parameter), the compiler must be able to decide, unambiguously, the intended type of the variable based on the expression that is assigned for initialization. The null value does not provide type information—it is assignment-compatible with any reference type. So, compilation would fail.

Changing the declaration to the following would allow option D to work:

var person = (Person) null;

Option A is correct. It uses the newer “pattern matching for instanceof” feature that was added (after several previews) in Java 16 as JEP 394. The effect is that if the deserialized object is, in fact, assignment-compatible with the Person type, the variable p is declared and initialized with the reference to that object. The scope of p is such that it’s usable only in the parts of the code where it has definitely been initialized. For example, if there were an else clause on the if statement, p would be out of scope in that else clause.

Conclusion. The correct answer is option A.

Source: oracle.com

Related Posts

0 comments:

Post a Comment