[concurrency-interest] Joda-Time immutability

Mark Thornton mthornton at optrak.com
Tue Jun 21 04:11:56 EDT 2011


On 21/06/11 07:27, Mark Thornton wrote:
> On 20/06/11 11:33, Stephen Colebourne wrote:
>> In Joda-Time way back when we structured the code in a complex manner
>> and then claimed immutability. This is causing difficulty to try and
>> obey proper immutability standards, and I'd like any ideas on fixes.
>>
>> Consider the "immutable" class DateTime. The hierarchy is as follows:
>>
>> AbstractInstant
>> AbstractDateTime
>> BaseDateTime
>> DateTime / MutableDateTime
>>
>> https://github.com/JodaOrg/joda-time/tree/master/src/main/java/org/joda/time 
>>
>> https://github.com/JodaOrg/joda-time/tree/master/src/main/java/org/joda/time/base 
>>
>>
>> The two Abstract prefixed classes are not an issue, as they just share
>> code and contain no state. However the BaseDateTime contains all the
>> state (and DateTime/MutableDateTime contain no state).
>>
>> As a result of this (bad) design, the instance variables in
>> BaseDateTime are not final (as they need to be mutated by the
>> MutableDateTime subclass). The DateTime ("immutable") subclass is thus
>> storing its state in regular mutable variables in BaseDateTime. Under
>> the memory model, claiming DateTime as immutable is wrong.
> A possible solution:
>
> Make the fields in BaseDateTime final.
> DateTime is left unchanged.
> Duplicate the fields in MutableDateTime with getter/setters referring 
> to the new (mutable) fields.
>
> Add a readObject method to MutableDateTime which calls 
> ObjectInputStream.readFields. If the new fields are present (test 
> using GetFields.defaulted) then we are restoring from a serialization 
> of the new form of the class; just restore them as usual. If the 
> fields are missing, then the serialized form was from the old class, 
> in this case copy the values from the immutable values in BaseDateTime.
>
> Note I have not tried this.
>
> Mark Thornton
>
An even simpler method would modify MutableDateTime as follows

public class MutableDateTime extends BaseDateTime {
    private long iMillis;
    private Chronology chronology;

    private void readObject(ObjectInputStream in) throws ... {
       iMillis = super.getMillis();
       chronology = super.getChronology();
       in.defaultReadObject();
    }

    public long getMillis() {return iMillis;}
    public Chronology getChronology() {return chronology;}

    // ...
}

This should be backward compatible with existing serialized instances 
while allowing the fields in BaseDateTime to be final. It comes at the 
expense of a slightly larger MutableDateTime object, and slightly slower 
deserialization.

Mark Thornton




More information about the Concurrency-interest mailing list