[concurrency-interest] Joda-Time immutability

Eamonn McManus eamonn.mcmanus at oracle.com
Mon Jun 20 15:26:58 EDT 2011


I would suggest mirroring the mutable fields in BaseDateTime with final 
fields in DateTime. Since existing serialized instances of DateTime will 
not have these fields, you will need a readResolve method to set them in 
that case. In order for serialized instances of the new DateTime to work 
with older versions, you just need to set the BaseDateTime fields as 
well. Something like this:

public final class DateTime extends BaseDateTime {
     private final long millis;

     public DateTime(long millis) {
         super(millis);  // for serializing to old versions
         this.millis = millis;
     }

     @Override public void getMillis() {
         return this.millis;
     }

     private Object readResolve() {
         if (getMillis() != super.getMillis()) {
             // for deserializing from old versions
             return new DateTime(super.getMillis());
         } else {
             return this;
         }
     }
}

If the fields in question are references rather than primitives, or if 
DateTime is not final, then the considerations mentioned in Effective 
Java 2, item 77, apply.

Éamonn

On 20/6/11 8:10 PM, Stephen Colebourne wrote:
> Java 7 Javadoc:
> "If the underlying field is final, the method throws an
> IllegalAccessException unless setAccessible(true) has succeeded for
> this Field object and the field is non-static. Setting a final field
> in this way is meaningful only during deserialization or
> reconstruction of instances of classes with blank final fields, before
> they are made available for access by other parts of a program. Use in
> any other context may have unpredictable effects, including cases in
> which other parts of a program continue to use the original value of
> this field. "
>
> So this approach fails. Back to square one.
>
> Any other suggestions?
>
> Does this work?
>
> class DateTime extends BaseDateTime {
>   private transient volatile fixBadDesign;
>
>   publc DateTime(long millis) {
>     super(millis);
>     fixbadDesign = this;
>     DateTime fixed = fixbadDesign;
>   }
>
> }
>
> Stephen
>
>
> On 20 June 2011 18:45, David M. Lloyd<david.lloyd at redhat.com>  wrote:
>> On 06/20/2011 12:32 PM, Stephen Colebourne wrote:
>>>
>>> On 20 June 2011 17:52, Attila Szegedi<szegedia at gmail.com>    wrote:
>>>>
>>>> Well, to me it looks like it's implemented:
>>>> import java.lang.reflect.Field;
>>>> public class TestFinalField {
>>>>    public final int x = 1;
>>>>    public static void main(String[] args) throws Exception {
>>>>      TestFinalField tff = new TestFinalField();
>>>>      Field f = tff.getClass().getField("x");
>>>>      f.setAccessible(true);
>>>>      f.set(tff, 2);
>>>>      System.out.println(tff.x);
>>>>    }
>>>> }
>>>> This prints "1", and not "2". So, setting of a final field is actually
>>>> silently ignored with setAccessible(true), for better or worse. Without
>>>> setAccessible(), it will actually throw an exception. With the "final"
>>>> qualifier removed from the field, it prints "2", as expected. I tested it
>>>> with both latest Java 6 and on the b145 build of OpenJDK 7, and both
>>>> behaves
>>>> as described.
>>>
>>> Well thats weird, because my change works and passes the tests in
>>> Joda-Time.
>>>
>>> https://github.com/JodaOrg/joda-time/commit/067983f2684fa9e9ca4af4ef73b09e2be2f70001#diff-8
>>>
>>> Anyone know what is going on? Can this be sufficiently relied on? I
>>> haven't really got a workable alternative.
>>
>> AFAIK the only time you can count on this working is if you've constructed
>> an object instance without calling its constructor (a la serialization).  In
>> other words the JVM is allowed to assume that the final field won't change
>> and optimize accordingly.
>>
>> I wouldn't rely on this trick for updating a field outside of a readObject()
>> method.
>>
>> --
>> - DML
>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest


More information about the Concurrency-interest mailing list