More quiz questions available here
You are working to enhance a legacy application, in particular to add serialization support and add more constraints to new business objects. The legacy application class looks like this.
public class Person {
private String name = null;
public Person() {}
public Person(String s) {
name = s;
}
}
You’ve also added a new application class.
public class EnhancedPerson extends Person implements Serializable {
public EnhancedPerson(String s) {
super(s);
if (s == null || s.length() == 0) {
throw new IllegalArgumentException("Invalid name");
}
}
}
Which statement is correct? Choose one.
A. | The EnhancedPerson class may not participate in serialization because its superclass is not serializable. |
|
B. | The EnhancedPerson class may not participate in serialization because it does not have a zero-argument constructor. |
|
C. | The EnhancedPerson class can be serialized but cannot be deserialized. |
|
D. | Immediately after deserialization, the name field of an EnhancedPerson will have a null value. |
|
E. | The EnhancedPerson class will always throw IllegalArgumentException during deserialization. |
Answer. This question investigates the deserialization process of an object that has a nonserializable parent type. Of course, every object has a nonserializable parent because, even if nothing else were true, java.lang.Object
itself falls into this category.
This first observation tells you that option A must be incorrect because a nonserializable parent type is inevitable and, therefore, cannot possibly prevent serialization and deserialization.
Two more rules regarding the serialization system are relevant to answering this question.
From those two points, you can see that option B is incorrect.
Option C is also incorrect because nothing in the code prevents deserialization. If the zero-argument constructor of Person
were private
, or if it did not exist, this option would be correct.
Option D is correct because the name field belongs to the Person
aspect of the EnhancedPerson
object. Such fields are not part of the serialized information. As noted earlier, when the Person
instance is re-created, this is done by calling the zero-argument constructor of Person
. Because of this, the name
field will be initialized to null. Of course, this would also be the case if the assignment of null were not present in the code, because the memory allocated for an object is always zeroed before it becomes available for use as the new object.
Regarding why option E is incorrect, recall that the deserialization process for (nonrecord) classes does not call any constructor in the Serializable
aspects of the object. This means that the code in the EnhancedPerson
constructor that validates the supplied name will not be called; therefore, no exception can be thrown.
This discussion raises questions. In the current design, deserialization creates an EnhancedPerson
object with a null name
field. The validation in the constructor is clearly intended to make this impossible. There would be aspects to address in restoring this integrity.
One aspect would be to ensure that the name field is immutable (the Person
class currently has no setters and name
is private, but the class is clearly a skeleton because it has no usable methods). Alternatively, you could ensure that all changes are controlled by the EnhancedPerson
in a way that keeps it valid.
The second aspect, which is more relevant to this question, would be to ensure that any EnhancedPerson
object deserialized from a data stream conforms to the validity rules. This can be accomplished by providing a private readObject
method. This method allows you to take control of the deserialization process. In the following example, the object is read from the stream using the default mechanism, but then it’s checked to determine if it is valid. If it’s not valid, the exception that’s thrown will cause the deserialization to be abandoned.
private void readObject(ObjectInputStream ois) throws
IOException,
ClassNotFoundException {
ois.defaultReadObject();
if (name == null || name.length() == 0) {
throw new InvalidObjectException("Invalid name");
}
}
Conclusion. The correct answer is option D.
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.