Generic clone for deep copying - is this any good?


C

castillo.bryan

I just came across a class that uses serialization to clone itself.
Its a class that is a base class for about 30 different classes that
represent items stored in a relational database. I understand that the
programmer did this so they could clone any object inherting from the
base class, without writing anything else. I'm not sure if this is
really a good idea or not though. Any opinions?


public Object clone() {
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(this);
bais = new ByteArrayInputStream(baos.toByteArray());
ois = new ObjectInputStream(bais);
return ois.readObject();
}
catch (ClassNotFoundException cnfe) {
throw new RuntimeException(cnfe);
}
catch (IOException ioe) {
throw new RuntimeException(ioe);
}
finally {
if (oos != null) try { oos.close(); } catch (IOException ioe) {}
if (ois != null) try { ois.close(); } catch (IOException ioe) {}
}
}
 
Ad

Advertisements

T

Thomas Hawtin

Roedy said:
It is a very roundabout way to clone. The ordinary clone implemented
in a base method will do the same job.

Object.clone does a very shallow copy. Serialisation does a very deep
clone. Different things.

Usually what you want is some kind of intermediate clone. For instance,
ArrayList.clone doesn't clone its stored elements, but more than a
bitwise clone as it must copy the array.

BTW: Serialisation will have poor performance (particularly with Sun's
implementation, allegedly). That may or may not be a problem.

Tom Hawtin
 
T

Thomas Hawtin

public Object clone() {

Using a different method name (or 1.5), you could return a more specific
type.
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;

What's the point in all of that? And I hate those initials.
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(this);

I don't know if it actually makes any difference, but you should flush here.
bais = new ByteArrayInputStream(baos.toByteArray());
ois = new ObjectInputStream(bais);
return ois.readObject();
}
catch (ClassNotFoundException cnfe) {
throw new RuntimeException(cnfe);
}
catch (IOException ioe) {
throw new RuntimeException(ioe);
}
finally {
if (oos != null) try { oos.close(); } catch (IOException ioe) {}
if (ois != null) try { ois.close(); } catch (IOException ioe) {}
}

As you aren't dealing with any actual resources, I don't think there's
any need for the finally. Unless anyone know different?

Tom Hawtin
 
Ad

Advertisements

R

Roedy Green

What's the point in all of that? And I hate those initials.

that's my fault . I wanted short names for the file i/o amanuensis
that I could use to tie together disparate code generated in many
different places.

bais = Byte Array Input Stream.
 

Top