The question
I have a Serializable class (let's call it A) with a non-transient boolean field, and a subclass (B) for which that same field should be transient. How can I do this?
More precisely, I wish the field to be restored to the default boolean value (false) when deserializing B, though I want it to be restored to the correct value when deserializing A. The other fields inherited from A should be restored nonetheless.
Functionnally, A represents an object which is restored between sessions, and B is a particular type of A whose state should be reset on each new session.
Quick code sample:
public class A implements java.io.Serializable {
private String label;
// non-transient
private boolean field;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public boolean isField() {
return field;
}
public void setField(boolean field) {
this.field = field;
}
}
public class B extends A {
// field should be transient for this class
// label should remain non-transient
}
Some possible solutions I chose not to retain
An easy solution would be to change B extends A to A extends B, make the field transient, and add a writeObject() to A to serialize the field. However, B extends A has a functional meaning, and I am not convinced it would be wise to revert it.
I could implement a readObject() method which would overwrite the deserialized value for the field. However, this feels like a dirty solution and I do not wish to use this unless no other choice is left.
I tried to write a writeObject() method to emulate a transient field, but it does not work and I cannot tell why. If anybody has a clue, that might be my solution:
public class B extends A {
private void writeObject(ObjectOutputStream out) throws IOException {
// save current state
boolean field = isField();
// synchronized to make sure this instance is not interrogated
// while changed for serialization
synchronized (this) {
// emulate transient state and serialize
setField(false);
out.defaultWriteObject();
// restore state
setField(field);
}
}
}
Edit: #rocketboy's solution using shadowing works, but I am uncomfortable with shadowing as it will leave one unused field (A's non-transient field will never be used, while B's transient version will be written and read). It might be a solution though. Do experimented Java developers think this is a clean solution?
public class B extends A {
// shadow A's field
private transient boolean field;
#Override
public boolean getField() {
return field;
}
#Override
public void setField(boolean field) {
this.field = field;
}
}
The answer
Following #m1o2's advice, I have been able to implement my solution using the Externalizable interface:
public class B extends A implements java.io.Externalizable {
// Do not forget to have a public no-arg constructor
// for Serialization to work
public B() {
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
// Write only the fields I am interested in
out.writeObject(getLabel());
}
#Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
// Read the serialized fields IN THE ORDER THEY WERE WRITTEN
setLabel((String) in.readObject());
}
}
Please note however that this is applicable because A and B are simple classes. For classes with many fields and a tendency to evolve, this could cost more (except maybe if using some code based on reflection).
If you don't care about the Superclass fields (all of them) you can use Externalizable interface
Related
Is there any advantage to storing a reference to a child instance field in the base class, as opposed to always calling an abstract getter when accessing it in the base class?
Suppose I have a base class like below:
public abstract class BaseClass {
abstract String getText();
public void printText() {
System.out.println(getText());
}
}
And a child class like below where getText() is returning a field that will never change.
public ChildClass extends BaseClass {
private String text = "blah";
#Override
public String getText() {
return text;
}
}
Is there any advantage/disadvantage to converting to the below instead?
public abstract class BaseClass {
abstract String getText();
private String text;
public void printText() {
System.out.println(text);
}
#PostConstruct
public void postConstruct() {
this.text = getText();
}
}
Regarding the use of PostConstruct, and I will refer you to this question to elaborate on that part, but essentially in combination with dependency injection/polymorphic methods it can make sense to use it to make sure you have a fully initialized object.
In general I would say the two approaches you suggest are not equivalent, because the classes have different behavior. For your second class it is guaranteed that for every call to printText() the same text will be printed, whereas for your first version, the text may be different every time, since the implementation of getText() is delegated to the implementing child-class. Thus the second version has an invariant the first one does not. Whether or not this is desirable or not is another question you need to evaluate in your concrete context.
I'm using spring-data-neo4j and I have two node entities, Person and Owner extends Person
When I save person, it gets the label :Person, and when I save an owner, it gets the labels :Owner and :Person. Excellent. Exactly what I wanted.
Sometimes we have people that become owners, so I'd like to convert that person to an Owner and add the missing data (such as properties).
Obviously downcasting doesn't work. There is a way I've heard of where you can get a subclass to call its superclass with parameters. I'd like to avoid the adapter pattern as there will be hundreds of inherited fields from Person.
How do I "construct" an Owner from a Person?
/*** MAIN CLASS ***/
public class Application {
public static void main (String[] args) {
Person p = personRepository.findByEmail ("joesoap#example.com");
Owner o = new Owner(p); // Trying to construct a person from an owner
o.addProperty (...);
ownerRespository.save(o);
}
}
/*** PERSON ***/
#NodeEntity
public class Person {
public Person(Person person) {
this = person; // Obviously this won't work, but I can't think of the solution...
}
String fullName;
String email;
}
/*** OWNER ***/
#NodeEntity
public class Owner extends Person {
public Owner(Person person) {
super (person);
}
public List<Property> properties;
}
Java classes were never meant to handle cases where one wants to make an object of one type into another type. Obviously treating a subclass as its superclass, or treating a class as an object which implemented an interface, were intended, but Java just has no good way of converting an object of one class into an object of another class.
You could convert the object to XML and then read the superclass fields into the subclass; kind of a brute-force-leave-the-XML-in-memory approach.
But I think what you have is a problem where Owner should not be represented by a subclass, for the specific reason that you sometimes want to convert from one class to the other. I think your Person class should have a field of a type containing owner information, null if the person is not also an owner.
This is what you do when you need to clone an object. Unfortunately the only way is to set each property manually:
class Test {
private String prop1;
private String prop2;
public Test() {}
public Test(Test test) {
setProp1(test.getProp1());
setProp2(test.getProp2());
}
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
public String getProp2() {
return prop2;
}
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
So in your case you call the cloning constructor, then setting the extra parameters in Owner
Downcasting is only allowed if there is a chance that it will succeed at runtime. In your case you would want to do as #arcy stated: add the extra parameters and initialize them as null if the person is not also an owner.
As mentioned in some other answers, creating a subclass instance from an instance of its superclass has its drawbacks, and has no direct support in Java. The resulting subclass instance is typically incomplete since it is only a clone of the superclass fields, and would then need additional field set-calls to populate subclass-specific fields. This might not be an issue in your application. Solving this through composition as suggested by #arcy is another decent option.
If you must create a subtype instance from a supertype instance, then copy-via-serialization is the best option. The key is to choose a flexible and high-performing serialization mechanism, and something better than native Java serialization. A library like Kryo is one decent option.
Using Kryo you could create a utility class to help register the serializers for the classes involved, then perform the clone-to-subclass-instance:
public class KryoDowncastCloneUtil {
private static final KryoDowncastCloneUtil instance = new KryoDowncastCloneUtil();
public static KryoDowncastCloneUtil instance() {
return instance;
}
private final Kryo kryo = new Kryo();
public <A, B extends A> void register(Class<A> superClass, Class<B> subClass) {
final Serializer<A> superClassSerializer = new FieldSerializer<>(kryo,
superClass);
// the superClass serializer is registered for both the superClass and its subClass
kryo.register(superClass, superClassSerializer);
kryo.register(subClass, superClassSerializer);
}
public <A, B extends A> B copyAndDowncast(A superClassInstance, Class<B> subClass) {
byte[] buffer = null;
try (final ByteArrayOutputStream stream = new ByteArrayOutputStream();
final Output output = new Output(stream)) {
kryo.writeObject(output, superClassInstance);
output.flush();
buffer = stream.toByteArray();
} catch (IOException e) {
// these are only from auto-close, swallow
} // auto-close stream, output
final B subClassInstanceClonedFromSuperClassInstance = kryo.readObject(new Input(
new ByteArrayInputStream(buffer)), subClass);
return subClassInstanceClonedFromSuperClassInstance;
}
}
The key here is that the same serializer, the one for the super-class A, is registered for serializing both the super-class and its sub-class B. This allows an instance of subclass B to be instantiated from the field data serialized from A - its own fields will be left null. You can then add some syntactic sugar to actual classes if desired:
public class Owner extends Person {
static {
KryoDowncastCloneUtil.instance().register(Person.class, Owner.class);
}
// ...
public static Owner fromPerson(Person person) {
return KryoDowncastCloneUtil.instance().copyAndDowncast(person, Owner.class);
}
}
In my application I have few types of holder objects, which primary purpose is to store heterogeneous related data. Their lifecycles can be divided into two parts:
Collecting data as soon as it becomes available;
Providing read-only access to stored data for the rest of a holder's life.
It is very tempting to make the holders immutable, but the data is not available at one time to be passed to a constructor. The simplest workaround I see is to make two versions of a holder class, one being mutable, and another being not:
public class MutableHolder {
public int field1;
public String field2;
// ...
public Object fieldN;
}
public class Holder {
public final int field1;
public final String field2;
// ...
public final Object fieldN;
public Holder(MutableHolder mutableHolder) {
this.field1 = mutableHolder.field1;
this.field2 = mutableHolder.field2;
// ...
this.fieldN = mutableHolder.fieldN;
}
}
However, I feel that this approach is violating the DRY principle (I must not forget to update both classes' fields as well as the constructor if I want to change anything) and is error prone. So here is my question: are there any existing patterns that I'm not aware of for implementing both mutable and immutable versions of a holder object?
Edit
I've suddenly found out that the code above is a very barebone version of the Builder pattern (see this or this). This makes me think that in this case DRY violation is considered acceptable.
I also have been stumbling over this for a while. Here is a design pattern I have come up with that I have not seen elsewhere.
public class Bob
{
// member variables
private int value;
// simple constructor
private Bob()
{
value(0);
}
// constructor with value
private Bob(int value)
{
value(value);
}
// get value
public final int value()
{
return this.value;
}
// set value
private final void value(int value)
{
this.value = value;
}
// mutable class modifies base class
public static class Mutable extends Bob
{
// simple constructor
private Mutable()
{
super();
}
// constructor with value
private Mutable(int value)
{
super(value);
}
// set value
public final void value(int value)
{
super.value(value);
}
}
// factory creator for immutable
public static final Bob immutable(int value)
{
return new Bob(value);
}
// factory creator for mutable
public static final Mutable mutable()
{
return new Mutable();
}
// another mutable factory creator
public static final Mutable mutable(int value)
{
return new Mutable(value);
}
}
The class is not final, subclassing should be safe.
All of the constructors must be private.
public accessors should be final.
private mutators in the base class should be final.
public mutators in the Mutable class should be final.
Use factory methods to construct immutable and mutable objects.
This is like the subclass mutable pattern, but since the Mutable class is an inner class, it has access to private fields and methods in the base class, so nothing needs to be protected which could possibly be overridden. The base class is just like a standard mutable class, except the constructors and mutators are private. The mutable subclass is a thin layer (every method is super...) that exposes the mutators.
To create an immutable instance: Bob test1 = Bob.immutable(99); To create a mutable instance: Bob.Mutable test2 = Bob.mutable();
Another possible solution is the State design pattern. Since it main concept is altering an object's behavior when its state changes. Also allows an object to alter its behavior when its internal state changes. The object will appear to change its class.
In your case you can consider the following implementation:
//maintains an instance of a ConcreteState subclass that defines the current state
public class Holder {
//your code
}
//encapsulating the behavior associated with a particular state of the Holder
public abstract class State{
//your code
}
//implements a behavior associated with a state of Holder
public class MutableHolderState extends State {
//your code
}
//implements a behavior associated with a state of Holder
public class ImmutableHolderState extends State {
//your code
}
I have a parent class with methods for writing and reading it from the db. The problem is I have a static method which I want to generalise. What is the best practice for doing this? I've came up with some solutions but all don't work with the static method.
Is there a way to force the childobject to implement the abstract method?
Parent Class:
public class Data_object {
public byte[] toByteArray() throws IOException {
return null;
}
public static Data_object fromByteArray(byte[] data){
return null
}
}
Child class:
public class ModelObject extends Data_object {
public static Data_object fromByteArray(byte[] data){
ModelObject result = new ModelObject();
//set data from byte arrray
return result;
}
}
thanks
A static method in Java can't be abstract and you can't override it. So you can't force a subclass to implement a certain static method.
The only way out is to require the static method by convention (like a note in the accompagnying JavaDoc) and using reflection to ensure at runtime (or at build time), that the subclass implements the required static method.
BTW - this is a common "pattern". Serializable does not define any methods, but it's documentation mentions three methods:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
The "object serialization framework" now uses reflection to test, if those methods are implemented by a class and, if yes, invokes those methods.
But I recommend looking for other solutions before using this strategy.
Static methods can't be overridden. You can only hide superclass methods by defining a method with same name and signature in the subclass, but it's quite confusing and therefore generally not recommended. The original superclass method could be still accessed by, for example, ((SuperClassName) subClassInstance).staticMethod().
In your case it's probably better to make the method non-static.
Inheritance does not apply to static methods that way. You call a static method on a specific class, like this:
MonkeyModelObject.fromByteArray(data)
Even when you do this from "inside" a class, you're behind-the-scenes still invoking that specific method on that specific class. So if you "override" a static method, you're just making a new method with the same name in another class (the child class). There's no run-time selection of methods for static methods.
For the specific case that you're working on, it seems like you're doing serialization from/to byte arrays. Perhaps you're serializing messages from a network stream, or something like that? I would recommend the following approach, maybe this pseudocode can inspire you:
abstract class Message
{
void write(stream)
{
stream.write(getMessageTypeCode());
writeParameters(stream);
}
abstract int getMessageTypeCode();
abstract void writeParameters(stream);
abstract void readParamters(stream);
}
class ChatMessage
{
String text;
int getMessageTypeCode() { return 1; }
void writeParameters(stream)
{
stream.write(text);
}
void readParameters(stream)
{
text = stream.read();
}
}
class MessageDecoder
{
Message decode(stream)
{
int type = stream.read();
message = createMessage(type);
message.readParameters(stream);
return message;
}
Message createMessage(int type)
{
if (type == 1)
{
return new ChatMessage();
}
throw new error;
}
}
What I mean is:
public class SomeBackingBean {
protected String someString;
public void setSomeString (String str) {
this.someString = str;
}
public String getSomeString {
return someString;
}
}
It was just a general case for a general answer.
Now second example:
public abstract class AbstractBean<T extends EntityInterface> {
protected T entity;
public void setEntity (T t) {
this.entity = t;
}
public void getEntity () {
return entity;
}
protected ReturnType calculateSomethingCommon () {
//use entity (knowing that it implements EntityInterface)
//to implement some common for all subclasses logic
}
}
public class ConcreteBean extends AbstractBean<ConcreteEntity> {
...
//and here we can write only specific for this bean methods
...
}
Is second example an example of bad practice too?
In general, protected variables violate object oriented principles. You're giving other objects direct access to member variables. By doing so, you form tighter coupling and it makes it harder to change the variable, since other objects are directly using it. It also means you can't do things like validate when it's set, add logging around getters/setters, etc.
If, for example, you have a PropertyChangeListener registered to properties for a bean, any registered listeners might not be notified if a protected property is changed directly by a sub-class.