PowerPoint slides

Download Report

Transcript PowerPoint slides

Serialization, Cont’d
Administrivia
• Reminders:
• Swing/events quiz (group/indiv): next Mon,
Feb 14
• Book text, BUT ALSO try some demo
programs yourself
• Reading 1: due Mon Feb 21
• Update to P1 M3: write query results to a file
• Example format will be in P1 spec v. 1.2
• Adherence to format spec is critical!
Gotchas #0.5
• Suppose:
•
class Foo extends Bar implements
Serializable
• but...
•
Bar
does not implements Serializable
• What happens when you (de-)serialize Foo?
Serialization order of ops
•
ObjectInputStream.readObject(myObj)
1. Loads class name → CName
2. Loads class by searching for CName on
$CLASSPATH → CObj
3. Checks CName’s class version (*)
4. Calls CObj’s no-arg constructor to create a
“blank” object of type CName → tmp
5. Calls tmp.readObject(stream) to load tmp
1. Usually same as
stream.defaultReadObject
2. May recurse into loading sub-objects
Superclasses, cont’d
•
Foo
and Bar must exist on class path
•
Bar
must provide a no-arg constructor
• Or step 2 fails
• Or step 4 fails
• Override Foo.readObject()/writeObject() to
save/load Bar’s protected/private state
•
Foo must have access or Bar must
protected accessor methods
provide
Superclasses, cont’d
• Order of operations (deserializing Foo):
• Java calls Foo’s no-arg constructor
• Java calls Bar’s no-arg constructor
• Java calls Foo.readObject()
•
Foo.readObject() reads Bar’s
initializes the Bar part of Foo
•
Foo.readObject()
•
Foo.readObject()
saved state;
reads its own saved
state and updates its own saved data
calls readObject() for
each of its child objects
Gotchas #1
• Efficiency
• You can just mark MondoHashMap as
Serialziable
and let Java do all the hard work
• But, that’s not as efficient as you could be, and
might be wrong
• By default, Java will store entire internal
including null values ⇒ lot of storage
overhead
_table,
• Wasting time to load/store all those null
entries
•
hashCode()s
of keys may not be same after
Gotcha #2
• Backward compatibility
• Suppose: You write class Foo v. 1.0
• Serialize an instance of Foo to file “foo1.0.dat”
• Later, add new private members to Foo ⇒ Foo
1.1
• Keep public methods/data all the same
•
should have same semantics and
be interchangeable w/ Foo 1.0
Foo 1.1
• What happens when you deserialize Foo 1.1
from foo-1.0.dat?
Serial versioning
• Issue is: in code, only changes to public or
protected
members make any difference
• (So long as semantics of methods
unchanged)
• With Serialization, all of a sudden, private
members now also are part of the “object
signature”
• (Why doesn’t this happen in single program
run?)
• Have to be very careful not to muck up
internals in a way that’s inconsistent w/
Serial versioning, cont’d
• Example:
•
•
// version 1.0
public class MyClass implements Serializable
{
public MyClass(int i) {
_data=2*i;
}
private int _data;
}
•
•
•
•
•
•
•
// version 1.1
public class MyClass implements Serializable
{
public MyClass(int i) {
_data=3*i;
// SEVERE NO-NO!
•
•
Serial versioning, cont’d
• Java helps as much as it can
• Tracks a “version number” for each class that
changes when the class changes
“substantially”
• Fields changed to/from static or transient
• Field or method names changed
• Data types changed
• Class moves up/down in class hierarchy
• Does not track code, local vars, comments,
etc.
Serial versioning, cont’d
• Java version number comes from names and
signatures of all data and method members of
a class
Names/sigs don’t change ⇒ Java won’t
notice a change
⇒ If you want Java to detect a change,
change a name
But if you’ve only changed names or refactored
private functionality, you want to be able to tell
Java that nothing has changed about your
class
Can lie to Java about version number:
•
•
•
••
static final long serialVersionUID=-
Design Exercise
Design exercise: reiterate
• Given
• An Iterator object (returned by some
method)
• A function, f: public Object f(Object)
• Design:
• class ReIterator implements Iterator
• Such that:
•
•
•
ReIterator.next()
Iterator.next()
returns f applied to
is interchangeable (call to f not
hardcoded in to ReIterator)
ReIterator requires only O(1) space
f()