Adding immutable class modifier

155 views
Skip to first unread message

BradW

unread,
Jul 12, 2011, 7:45:06 PM7/12/11
to java-language...@googlegroups.com
I believe that adding a new keyword (immutable) to the JLS will provide a means to simplify the process of creating
immutable classes.  Look here for my original proposal: http://www.java.net/forum/topic/jdk/java-se/jsr-proposal-immutable-class-modifier.

As a result of discussions elsewhere (https://groups.google.com/d/topic/guava-discuss/NIPDjdQ22i8/discussion),
I believe it may also be necessary to add another keyword: lazy.  This keyword would be used only in relation to instance variables that
need to be initialized lazily.  For instance, in class String:

private int hash;

as this is set only when it is first referenced through:

public int hashCode()

by changing it to:

private final lazy int hash;

this would then fulfill the requirements for immutability and flexibility.

Craig Berry

unread,
Jul 12, 2011, 7:47:48 PM7/12/11
to java-language...@googlegroups.com
One might imagine that it would be a runtime error to read a lazy
member before it's been written.

> --
> You received this message because you are subscribed to the Google Groups
> "Java Language Specification" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/java-language-specification/-/cNuSrAnBuikJ.
> To post to this group, send email to
> java-language...@googlegroups.com.
> To unsubscribe from this group, send email to
> java-language-speci...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/java-language-specification?hl=en.
>

--
Craig Berry
Software Engineer
Google (Santa Monica CA)

Raymond Rishty

unread,
Jul 12, 2011, 7:50:15 PM7/12/11
to java-language...@googlegroups.com
Brad,
How do you propose mutability to be checked?

My common-sense reaction was to require all fields to be immutable; there are, however, necessary exceptions, as in Guava's RegularImmutableList, which requires use of an array.

Arrays are necessarily mutable, and Guava has to promise that they are using it in an immutable way. I would suggest a warning in cases where members of a type that is not marked immutable are used in a class marked immutable. Then in cases where this is really what you want, you would add a @SuppressWarnings annotation.

--

Raymond Rishty

unread,
Jul 12, 2011, 7:53:33 PM7/12/11
to java-language...@googlegroups.com
How would lazy be implemented? The double-check idiom? What if one only requires the single-check idiom? java.lang.String famously uses the racy single-check idiom to cache hash codes.

BradW

unread,
Jul 12, 2011, 7:55:37 PM7/12/11
to java-language...@googlegroups.com


On Wednesday, 13 July 2011 07:47:48 UTC+8, Craig Berry wrote:
One might imagine that it would be a runtime error to read a lazy
member before it's been written.

Yes.  Perhaps there should be some mechanism for test whether or not a lazy member
has been initialized?  I'm not sure how that might be achieved.  Or where the responsibility
for such a test should reside.

Raymond Rishty

unread,
Jul 12, 2011, 8:03:36 PM7/12/11
to java-language...@googlegroups.com
This sounds like something that could be done at compile-time. Just like accessing a final field before its value has been set.

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 12, 2011, 8:10:47 PM7/12/11
to java-language...@googlegroups.com
My original proposal in full is below:

Subject: JSR Proposal - immutable class modifier

Description:
I would like to propose a change to the Java Language Specification (JLS), to include a new class modifier: immutable.
This modifier would be used in situations where an immutable object is needed to maintain data integrity, with ease
of code maintenance.

The idea is that the compiler would check that all instance variables of the implementing class, and its subclasses,
have been set to: final.  That is all.  By doing this, it prevents the data being potentially corrupted.  In addition,
a more complex implementation of this specification, could allow the compiler to 'imply' all instance variables are
final when they are not 'explicitly' set as such.  This would help in modifying legacy code, by simply allowing the
addition of the immutable modifier to a class' definition.

The same can be achieved by due diligence on the part of programmers, by themselves making sure that all the instance
variables are set as final, but this can be a problem later on, during the maintenance phase.  To assist myself in this,
I have created a 'tag interface' : Immutable.java/class, which is an empty interface. This helps me to remember that this
class' instance variables MUST be kept as final.  However, I am only human, and therefore subject to mistakes, such as,
forgetting to set an instance variable of a subclass of a class that implements 'Immutable', as final.  Thus breaking
the 'immutable' contract/state of the class.  This becomes even more of a problem, when dealing with third party libraries, where
it is desirable for a class to be both immutable and not final.  Thereby allowing the sub-classing of immutable classes to occur.

JLS changes:

8.1.1:
A class declaration may include class modifiers.

    ClassModifiers:
        ClassModifier
        ClassModifiers ClassModifier

    ClassModifier: one of
        Annotation public protected private
        abstract static final strictfp immutable
                                       ^^^^^^^^^

Add:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8.1.1.4:
The effect of the immutable modifier, is to require that all instance variables of the class, and all its subclasses,
be set either implicitly or explicitly, to final.
-------------------------------------------------------------
Discussion:

/**
 * This class is immutable
 * @author Brad Willcott
 */
public class immutable AnImmutableClass {

    /** Height of object */
    public final int height;

    /** Length of object */
    public final int length;

    /** Width of object */
    public final int width;

    /**
     * Constructs a new AnImmutableClass object.
     *
     * @param height of object
     * @param width of object
     * @param length of object
     */
    public AnImmutableClass(final int height, final int width, final int length) {
        this.height = height;
        this.length = length;
        this.width  = width;
    }
}


Note: The final modifiers used on the parameters of the constructor are NOT
a requirement of this specification, but simply a recommendation only.

-------------------------------------------------------------
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

JVMS changes:

2.8.2 Class Modifiers:

Add:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A class can be declared immutable to indicate that all its instance variables
are final <a href="#29882">(2.9.1)</a>, whether or not the variables themselves
are declared final.  Further, all subclasses of an immutable class
are also automatically immutable, whether or not the subclasses themselves
are declared immutable.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

BradW

unread,
Jul 12, 2011, 8:34:11 PM7/12/11
to java-language...@googlegroups.com
On Wednesday, July 13, 2011 8:03:36 AM UTC+8, Raymond Rishty wrote:
This sounds like something that could be done at compile-time. Just like accessing a final field before its value has been set.

It does seem more like a run-time issue.  How would the compiler know when a method might be called?
Having a run-time exception being thrown when a final lazy instance variable is accessed before it is initialized
is probably the best solution.  However, I would still like to be able to test for the state of the variable.

Any ideas on how?

Radu Grigore

unread,
Jul 12, 2011, 8:40:45 PM7/12/11
to java-language...@googlegroups.com
Just a quick note to point out relevant prior work:

C. Haack and Erik Poll
Type-based object immutability with flexible initialization

Raymond Rishty

unread,
Jul 12, 2011, 8:51:43 PM7/12/11
to java-language...@googlegroups.com
As a general rule, the earlier you can find a problem, the better. That is, in fact, what I would find attractive about an immutable keyword (or annotation). In the case of hashCode, all access to that field would typically be in a single method. My lazily-cached hashCode implementations typically are similar to the following:

private transient volatile hashCode;

public int hashCode() {
    int hashCode = this.hashCode;
    if (hashCode == 0) {
        hashCode = this.hashCode = Objects.hashCode(a, b, c);
    }

    return hashCode;
}

Perhaps instead you would have something like the following:

private transient final lazy hashCode;

public lazy hashCode() {
    this.hashCode = Objects.hashCode(a, b, c);
    return this.hashCode;
}

The first time this method is accessed, it will populate hashCode. Any future accesses to that method would simply return the cached value.

This is probably not exactly how you'd do it... just trying to push in the direction of a) don't make the programmer do something so complicated he is liable to shoot himself in the foot (e.g., the double-check idiom, which is the only one that ought to pass the test), and b) be able to reliably guarantee that the class will be immutable with the exception of lazy-initialized fields, which would be guaranteed to be initialized once.

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 12, 2011, 8:54:25 PM7/12/11
to java-language...@googlegroups.com
On Wednesday, July 13, 2011 7:50:15 AM UTC+8, Raymond Rishty wrote:
Brad,
How do you propose mutability to be checked?

Check out "My original proposal.." message.

My common-sense reaction was to require all fields to be immutable; there are, however, necessary exceptions, as in Guava's RegularImmutableList, which requires use of an array.

All instance variables would be either final (under original proposal), or final lazy (to be included in revised proposal).

Arrays are necessarily mutable, and Guava has to promise that they are using it in an immutable way. I would suggest a warning in cases where members of a type that is not marked immutable are used in a class marked immutable. Then in cases where this is really what you want, you would add a @SuppressWarnings annotation.

With arrays, things could get really messy.  We could required that any array allocated to a final instance variable, contain only:
(a) primitives, or
(b) immutable objects (inserted directly by the JVM), or
(c) references to immutable objects.

This could be done by walking through the arrays dimensions and testing all of its contents.  Potentially, very costly though.

However, I think that the real challenge would be in converting mutable objects into immutable objects on the fly, so to speak.
Such that by, passing a mutable object into an immutable object's constructor, you would be able to safely store that object into
a final instance variable and maintain the class' immutability contract.

Any ideas?


BradW

unread,
Jul 12, 2011, 9:06:47 PM7/12/11
to java-language...@googlegroups.com
On Wednesday, July 13, 2011 7:53:33 AM UTC+8, Raymond Rishty wrote:
How would lazy be implemented? The double-check idiom? What if one only requires the single-check idiom? java.lang.String famously uses the racy single-check idiom to cache hash codes.

I see lazy as just a keyword, used as an instance variable modifier, in conjunction with final

What it would mean to the compiler, is that it would need to find atleast one point in the enclosing class
where the variable is being set to a value.  This could be either in one or more constructors, and / or in one
or more non-static methods.  If not in ALL constructors, then it would HAVE to be in one or more methods as well.

For the JVM, it would mean checking that it has been initialized before any access is allowed, throwing a
run-time exception when necessary, and allowing it to be initialized only once.

Raymond Rishty

unread,
Jul 12, 2011, 10:20:01 PM7/12/11
to java-language...@googlegroups.com
So, how would you deal with a final instance of a mutable class. For example, suppose I had

private final List<String> products;

as an instance variable. What would prevent me from calling getProducts().add(productNumber)?

If, on the other hand, you had a rule that instance variables must be immutable, you would get a warning on the above (because List is not an immutable type); you would then switch to ImmutableList, which would be marked immutable, and the compiler would be happy.

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 13, 2011, 7:49:56 AM7/13/11
to java-language...@googlegroups.com
On Wednesday, July 13, 2011 10:20:01 AM UTC+8, Raymond Rishty wrote:
So, how would you deal with a final instance of a mutable class. For example, suppose I had

private final List<String> products;

as an instance variable. What would prevent me from calling getProducts().add(productNumber)?

If, on the other hand, you had a rule that instance variables must be immutable, you would get a warning on the above (because List is not an immutable type); you would then switch to ImmutableList, which would be marked immutable, and the compiler would be happy.

I'm not sure that this is relevant.  I believe that there are situations, with mutable classes, where you would want the current
handling of final instance variables.  That is, you lock the List to the variable, but still need to modify its contents.

In the case of an immutable class, then yes.  This would be a valid solution.  Further, it would, I think, be necessary
for it to be recursively immutable.

Raymond Rishty

unread,
Jul 13, 2011, 7:50:12 AM7/13/11
to java-language...@googlegroups.com
I've given this a little more thought, and I'm rather reluctant about the lazy keyword. I think your immutability constraint can be satisfied without it.

Suppose you had a class like the following:

public immutable abstract class Lazy<T> {
    private volatile T value;
    public abstract T initialize();
    public T get() {
        T value = this.value;
        if (value == null) {
            synchronized(this) {
                value = this.value;
                if (value == null) {
                    this.value = value = initialize();
                }
            }
        }

        return value;
    }
}

then in your immutable Foo class, you could have:

private final Lazy<Integer> hashCode = new Lazy<Integer>() {
    public Integer initialize() {
        return Objects.hashCode(a, b, c);
    }
}

public int hashCode() {
    return hashCode.get();

BradW

unread,
Jul 13, 2011, 7:52:30 AM7/13/11
to java-language...@googlegroups.com

I had a look at the abstracts.  Very interesting.  However, I'm not prepared to pay for the access,
at this time, so as to fully benefit from the books.  Maybe later.
 

Maaartin G

unread,
Jul 13, 2011, 8:32:01 AM7/13/11
to java-language...@googlegroups.com

Graham Allan

unread,
Jul 13, 2011, 2:22:07 PM7/13/11
to java-language...@googlegroups.com

I think that kind of defeats the point of immutability: clients should never see a change in state.  If multiple calls are made to retrieve a lazy value, they should probably just block until it's computed. Another possibility is that lazy values can only be calculated from the state of other immutable values, such that any data races that occur in retrieving it are guaranteed to be benign (a la String's hashCode()).

~ Graham

Radu Grigore

unread,
Jul 13, 2011, 3:54:33 PM7/13/11
to java-language...@googlegroups.com
Huh? The page I gave contains at least five links to the article and only one requires payment.

BradW

unread,
Jul 13, 2011, 8:59:25 PM7/13/11
to java-language...@googlegroups.com
On Wednesday, July 13, 2011 8:51:43 AM UTC+8, Raymond Rishty wrote:
As a general rule, the earlier you can find a problem, the better. That is, in fact, what I would find attractive about an immutable keyword (or annotation). In the case of hashCode, all access to that field would typically be in a single method. My lazily-cached hashCode implementations typically are similar to the following:

private transient volatile hashCode;

public int hashCode() {
    int hashCode = this.hashCode;
    if (hashCode == 0) {
        hashCode = this.hashCode = Objects.hashCode(a, b, c);
    }

    return hashCode;
}

Perhaps instead you would have something like the following:

private transient final lazy hashCode;

public lazy hashCode() {
    this.hashCode = Objects.hashCode(a, b, c);
    return this.hashCode;
}

Yes. Something like that.  The next question is do we want the JVM to simply ignore subsequent attempts to set
a final lazy inst var after initialization?  Or, do we want it to throw an exception?  Without an exception, you
could have code expecting the var to be changed, and have a potentially hidden bug, when it isn't.
 
The first time this method is accessed, it will populate hashCode. Any future accesses to that method would simply return the cached value.

This is probably not exactly how you'd do it... just trying to push in the direction of a) don't make the programmer do something so complicated he is liable to shoot himself in the foot (e.g., the double-check idiom, which is the only one that ought to pass the test), and b) be able to reliably guarantee that the class will be immutable with the exception of lazy-initialized fields, which would be guaranteed to be initialized once.

For me the KISS principle should be paramount.  I like it.  Especially your shooting analogy.  The simpler it is, the less chance we're likely to
foul up our code.  Some people like to complicate the heck out of things.

BradW

unread,
Jul 13, 2011, 9:04:03 PM7/13/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 2:22:07 AM UTC+8, Graham Allan wrote:

I think that kind of defeats the point of immutability: clients should never see a change in state.  If multiple calls are made to retrieve a lazy value, they should probably just block until it's computed. Another possibility is that lazy values can only be calculated from the state of other immutable values, such that any data races that occur in retrieving it are guaranteed to be benign (a la String's hashCode()).

I think the coding to achieve this restriction to using only "the state of other immutable values", would be interesting to see.  It would need to be in both the
compiler and the JVM (reflection).

However, I see you point.

Raymond Rishty

unread,
Jul 13, 2011, 9:26:10 PM7/13/11
to java-language...@googlegroups.com
This would not be unlike the static keyword. static methods can only use class-level variables that are static. Likewise lazy methods could only use immutable methods and immutable class-level variables.

That said, I'm still not convinced that using something like the Lazy class isn't a better solution for this. 

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 13, 2011, 9:29:50 PM7/13/11
to java-language...@googlegroups.com
On Wednesday, July 13, 2011 7:50:12 PM UTC+8, Raymond Rishty wrote:
I've given this a little more thought, and I'm rather reluctant about the lazy keyword. I think your immutability constraint can be satisfied without it.

Suppose you had a class like the following:

public immutable abstract class Lazy<T> {
    private volatile T value;

value here breaks the immutable contract. As an instance var it should be final.
 
    public abstract T initialize();
    public T get() {
        T value = this.value;
        if (value == null) {
            synchronized(this) {
                value = this.value;
                if (value == null) {
                    this.value = value = initialize();
                }
            }
        }

        return value;
    }
}

then in your immutable Foo class, you could have:

private final Lazy<Integer> hashCode = new Lazy<Integer>() {
    public Integer initialize() {
        return Objects.hashCode(a, b, c);
    }
}

public int hashCode() {
    return hashCode.get();
}
 
I see what you are getting at.  However, if this were allowed, then Lazy.class would not
be needed.  If we could have value as a non-final inst var, then why not have hashCode
as such?  Unfortunately, your solution is self-defeating.

Raymond Rishty

unread,
Jul 13, 2011, 9:35:05 PM7/13/11
to java-language...@googlegroups.com
Not quite. I failed to add the @SuppressWarnings annotation I'd alluded to earlier. You're right that any old user can do this himself... but, as you mentioned, do you really want to rely on people trying to remember the various lazy-initialization idioms, and most likely getting it wrong? Particularly if you want to enforce the "this can absolutely be set only once under any circumstances" rule, everyone has to use the double-check idiom, which is, of course, the hardest one to get right.

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 13, 2011, 9:55:07 PM7/13/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 9:35:05 AM UTC+8, Raymond Rishty wrote:
Not quite. I failed to add the @SuppressWarnings annotation I'd alluded to earlier. You're right that any old user can do this himself... but, as you mentioned, do you really want to rely on people trying to remember the various lazy-initialization idioms, and most likely getting it wrong? Particularly if you want to enforce the "this can absolutely be set only once under any circumstances" rule, everyone has to use the double-check idiom, which is, of course, the hardest one to get right.

In another posting you wrote this code:


public lazy hashCode() {
    this.hashCode = Objects.hashCode(a, b, c);
    return this.hashCode;
}

Now, I like the simplicity of it.  As I mentioned before, in relation to it, do we have the JVM just ignore the
assignment after the first time, or throw an exception.  If we forget the exception option, then this code
could be simplified as follows:

public lazy hashCode() {
    return this.hashCode = Objects.hashCode(a, b, c);
}

Here's a thought.  As the lazy keyword would be a modifier stored in the Class tree in the JVM, once it has been
initialized, why not remove the modifier from the var, thereby reducing it to just a final inst var.  What would happen
when a subsequent assignment was attempted?

If this is not workable, then some other state bit would need to be
set so the JVM can keep track of the state of the final lazy inst vars.

What do you think?


 

Raymond Rishty

unread,
Jul 13, 2011, 10:03:19 PM7/13/11
to java-language...@googlegroups.com
Why even have the var at all?

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 13, 2011, 10:34:49 PM7/13/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 9:26:10 AM UTC+8, Raymond Rishty wrote:
This would not be unlike the static keyword. static methods can only use class-level variables that are static. Likewise lazy methods could only use immutable methods and immutable class-level variables. 

I'm not sure where your going with this.  The immutable keyword, as I see it, is a class modifier, only.
I have seen others referring to immutable and mutable methods, but I have seen nothing yet, to convince me that
such would be of real use.  However, I am open to further discussion.

Further thought.  If we open the keyword lazy to allow it to be used as a modifier for a final method, and restrict
access to/assignment of final lazy inst vars to such methods, with the further restrictions you mentioned, then just
maybe you are onto something.  For example:

// AnImmutableClass.java

//~--- JDK imports ------------------------------------------------------------

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

//~--- classes ----------------------------------------------------------------


/**
 * This class is immutable
 * @author Brad Willcott
 * @Version 2.0
 */

public immutable class AnImmutableClass {

    public final List< Data > dataList;


    /** Height of object */
    public final int height;

    /** Length of object */
    public final int length;

    /** Width of object */
    public final int width;

    /**
Lazily initialized instance var */
    private final lazy int hash;  // <====== * * * * * *

    //~--- constructors -------------------------------------------------------


    /**
     * Constructs a new AnImmutableClass object.
     *
     * @param height of object
     * @param width of object
     * @param length of object
     */
    public AnImmutableClass(final int height, final int width, final int length, final Data[] dataArray) {

        this.height = height;
        this.length = length;
        this.width  = width;
        dataList    = Collections.unmodifiableList(Arrays.asList(dataArray));
    }

    //~--- methods ------------------------------------------------------------

    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        final AnImmutableClass other = (AnImmutableClass) obj;

        if (!Objects.equals(this.dataList, other.dataList)) {
            return false;
        }

        if (this.height != other.height) {
            return false;
        }

        if (this.length != other.length) {
            return false;
        }

        if (this.width != other.width) {
            return false;
        }

        if (hashCode() != other.hashCode()) {
            return false;
        }

        return true;
    }

    public final lazy int hashCode() {
        return hash = Objects.hash(height, length, width, dataList);
    }

    //~--- inner classes ------------------------------------------------------

    public static immutable class Data {

        final String name;
        final int    age;
        final long   time;

        //~--- constructors ---------------------------------------------------

        public Data(final String name, final int age, final long time) {
            this.name = name;
            this.age  = age;
            this.time = time;
        }
    }
}

Comments anyone?


Raymond Rishty

unread,
Jul 13, 2011, 10:47:02 PM7/13/11
to java-language...@googlegroups.com
Your class is mutable:

new AnImmutableClass(1, 1, 1, new Data[]{new Data("ray", 112, 17)}).dataList.removeAll();

Regarding my mention of immutable methods--you're right. I was referring to something that I had been thinking in my head, but hadn't yet flushed out.

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 13, 2011, 11:21:26 PM7/13/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 10:47:02 AM UTC+8, Raymond Rishty wrote:
Your class is mutable:

new AnImmutableClass(1, 1, 1, new Data[]{new Data("ray", 112, 17)}).dataList.removeAll(); 
 
package java.util;

...

public class Collections {

    ...

    public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
    }

    static class UnmodifiableList<E> extends UnmodifiableCollection<E>
                                  implements List<E> {
    ...
    }

    ...

    static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
        public boolean removeAll(Collection<?> coll) {
            throw new UnsupportedOperationException();
        }
    }
    ...
}

BradW

unread,
Jul 13, 2011, 11:27:20 PM7/13/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 10:03:19 AM UTC+8, Raymond Rishty wrote:
Why even have the var at all?

I assume you mean "hash"?  Well as you probably know, some hash-code calculations can be quite costly.
So, by doing them only once, and even then only when needed, is the most efficient use of processing time.

Raymond Rishty

unread,
Jul 14, 2011, 12:16:22 AM7/14/11
to java-language...@googlegroups.com
What I meant was that you could just have:

private lazy int hashCode() {
    return Objects.hashCode(a, b, c);
}

And the lazy modifier on the method could control the caching of the value once it's initialized. In other words, why even declare the var yourself--instead, just define the method and let the JVM do the work.

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

Raymond Rishty

unread,
Jul 14, 2011, 12:19:40 AM7/14/11
to java-language...@googlegroups.com
Fair enough--I hadn't noticed the wrapping you did in the constructor. But thats the point--you're not communicating immutability of the members, nor can you enforce it early. Just force use of immutable classes, and nobody could make the mistake of forgetting to wrap it. 

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

Maaartin G

unread,
Jul 14, 2011, 8:49:23 AM7/14/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 6:16:22 AM UTC+2, Raymond Rishty wrote:
What I meant was that you could just have:

private lazy int hashCode() {
    return Objects.hashCode(a, b, c);
}

And the lazy modifier on the method could control the caching of the value once it's initialized. In other words, why even declare the var yourself--instead, just define the method and let the JVM do the work.

This is a nice syntax and eliminates the problem of second assignment to the lazy variable mentioned above (ignore or throw). No visible variable, no problem.

BradW

unread,
Jul 15, 2011, 6:20:46 PM7/15/11
to java-language...@googlegroups.com
I'm not sure I like the idea of hidden variables.  How about this:

private final lazy int hash = Objects.hashCode(a, b, c);
...
public int hashCode(){
   return hash;
}

What I'm proposing is this.  We declare the inst var and its initialization as though it was a normal
final inst var,
but because of the lazy modifier, the actual initialization doesn't take place until the first time it's read!

This way, it looks like normal Java coding, with just the one main difference, the lazy modifier.
What do you think?


BradW

unread,
Jul 15, 2011, 6:22:19 PM7/15/11
to java-language...@googlegroups.com
On Thursday, July 14, 2011 12:19:40 PM UTC+8, Raymond Rishty wrote:
Fair enough--I hadn't noticed the wrapping you did in the constructor. But thats the point--you're not communicating immutability of the members, nor can you enforce it early. Just force use of immutable classes, and nobody could make the mistake of forgetting to wrap it. 

So how would you go from a mutable to an immutable object?
 

Raymond Rishty

unread,
Jul 15, 2011, 7:31:51 PM7/15/11
to java-language...@googlegroups.com
I would use ImmutableList

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

Morten Hattesen

unread,
Jul 16, 2011, 7:08:30 AM7/16/11
to java-language...@googlegroups.com
+1 for

private final lazy int hash = Objects.hashCode(a, b, c);

Very elegant, and universally usable. Also it follows the principle of "least surprise" (see How to design a good API and why it matters)

/Morten

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 16, 2011, 12:25:29 PM7/16/11
to java-language...@googlegroups.com
How about using an interface as follows: "Immutable.java"

/**
 * Used by mutable class to provide an <em>Immutable</em>
 * copy of itself.
 *
 * All implementations should be recursively 'immutable'.
 *
 * @author Brad Willcott
 */
public interface Immutable<T> {
    public T asImmutable();
}

I see this being used by all existing classes.  For example:

package java.util;
...

public class ArrayList< E > extends AbstractList< E >
        implements List< E >, RandomAccess, Cloneable, java.io.Serializable,
        Immutable<ImmutableArrayList> {

...
   public
ImmutableArrayList asImmutable(){
      return new
ImmutableArrayList(this);
   }
}

If every mutable class implemented this Immutable interface, then conversion to immutable
objects would be very simple.

I am going to do a version of java.util.ArrayList, and it super-classes and interfaces, that works
in this way, including their immutable counterparts.  I'll publish them here for comments.  Please
note, that this will be only to provide working examples.





Raymond Rishty

unread,
Jul 16, 2011, 12:31:43 PM7/16/11
to java-language...@googlegroups.com
I guess I'm a bit confused about this... Guava already provides ImmutableList that is immutable and can convert any iterable to an ImmutableList. What's missing?

--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

BradW

unread,
Jul 16, 2011, 3:45:10 PM7/16/11
to java-language...@googlegroups.com


On Sunday, July 17, 2011 12:31:43 AM UTC+8, Raymond Rishty wrote:
I guess I'm a bit confused about this... Guava already provides ImmutableList that is immutable and can convert any iterable to an ImmutableList. What's missing?

The problem is that Guava is not part of the JDK.  Also, the only reason I'm doing the coding, at this time, is to provide a working example, using the ideas put forward so far.
However, the "extras" will only show up in the comments, unfortunately.

BradW

unread,
Jul 16, 2011, 7:59:57 PM7/16/11
to java-language...@googlegroups.com
I have found a special case.

    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {...}

Are there any others out there?

BradW

unread,
Jul 26, 2011, 7:15:58 AM7/26/11
to java-language...@googlegroups.com
I have attached a copy of my example library.  I found it necessary to add another interface: Sealable.java.  See the javadocs or source code for details.

This zip includes only the Netbeans project files and the source code.  If you want the complied version with the javadocs, let me know.  The zip
is 2.1Mb in size.

BWImmutable-nb-0.1.zip

BradW

unread,
Aug 4, 2011, 8:09:13 PM8/4/11
to java-language...@googlegroups.com
Hi there,
I have just finished setting up a new project on Java Net:

http://jdk-immutability.java.net/

This discussion topic will continue to be the main place for open discussion on this topic.  If you are
interested in being involved, please let me know.

I have refactored the code, separating out the samples from the main library.  Also, they are now in the
base package: "net.java.*", as this is an open source project.  Please note, that this library is not
meant to remain a separate entity from the JDK.  The intention is for it to be merged into the JDK
at some future time.  The source is based on code copied from JDK 1.7.

Brad.

Maaartin G

unread,
Aug 4, 2011, 10:37:51 PM8/4/11
to Java Language Specification
On Aug 5, 2:09 am, BradW <b...@willcott.com> wrote:
> http://jdk-immutability.java.net/

I'd say your "lazy" is a bit too complicated. What about simply

private lazy int hashCode() {
int h = 7;
h = 31 * h + name.hashCode();
return h;
}

without any explicit variable declaration? There could be an
implicitly defined field $hashCode, or whatever.

You wrote
> public /* final lazy */ int hash; /* = hash(); */ // Method call not made until variable is referenced
This means you need an implicit boolean variable tracking if hash was
already referenced.

IMHO, nearly always the approach taken by String.hashCode() suffices:
Zero means either that the result wasn't computed yet, or that you
were unlucky enough to get 0 as a result. Unlucky because it means
that the value gets computed again and again. Fortunately, it's quite
improbable and so taking the risk is better than spending 4 or 8 bytes
(needed for a boolean considering the alignment). I'm not sure if
there are situations where you need to avoid the risk.

PS: The above hashCode doesn't make much sense, you probably meant
"int h = id" on the first line.

Morten Hattesen

unread,
Aug 5, 2011, 5:34:38 AM8/5/11
to java-language...@googlegroups.com
I believe the implicit lazy field (e.g. $hashCode) should be declared using the wrapper class java.lang.Integer.
That will remove the need for having to pick a magic "null" value that is unlikely to match a computed value. Even if this works for java.lang.String it cannot be guaranteed to work for other lazy instances. The lazy idiom should guarantee that only a single call is ever made to the lazy method.

Morten


--
You received this message because you are subscribed to the Google Groups "Java Language Specification" group.

Maaartin G

unread,
Aug 5, 2011, 7:02:19 AM8/5/11
to Java Language Specification
On Aug 5, 11:34 am, Morten Hattesen <morten.hatte...@gmail.com> wrote:
> I believe the implicit lazy field (e.g. $hashCode) should be declared using
> the wrapper class java.lang.Integer.

But isn't it more costly than using the additional boolean? At least
in case the field gets used?

What would you do in case of methods returning Integer where null is a
legal value? I could imagine a bad hack for this, but no nice
solution.

> That will remove the need for having to pick a magic "null" value that is
> unlikely to match a computed value. Even if this works for java.lang.String
> it cannot be guaranteed to work for other lazy instances. The lazy idiom
> should guarantee that only a single call is ever made to the lazy method.

I could imagine that sometimes the memory is more important. There
could be two kinds of "lazy", let's say strict and sloppy lazy. Of
course, using additional keywords is too bad.

BradW

unread,
Aug 5, 2011, 9:19:28 PM8/5/11
to java-language...@googlegroups.com
On Friday, August 5, 2011 10:37:51 AM UTC+8, Maaartin G wrote:
On Aug 5, 2:09 am, BradW <b....@willcott.com> wrote:
> http://jdk-immutability.java.net/

I'd say your "lazy" is a bit too complicated. What about simply

private lazy int hashCode() {
     int h = 7;
     h = 31 * h + name.hashCode();
     return h;
}

My hash() method's code is for show.  The idea is that with this declaration:
    public final lazy int hash = hash(); // Method call not made until variable is referenced
you get to use a method to initialize a final lazy instance variable.  Furthermore, the method is called by the JVM only once.  That being, the
first time the variable is referenced by, in this case:

    public int hashCode(){
        return hash;
    }
or directly, as it is a public variable.  Once the variable has been initialized, it is treated like any normal final variable.

The method:
    private lazy int hash(){
        int h = id;
        h = 31 * h + name.hashCode();
        return h;
    }
has the lazy modifier to designate it to be the init method for the final lazy hash variable. The naming is specific.  Note that this is private, and uses the actual variable name, because it is declared above as the field's initializer method: hash = hash();.  This keeps it simple.  No ambiguity.

You wrote
>  public /* final lazy */ int hash; /* = hash(); */ // Method call not made until variable is referenced
This means you need an implicit boolean variable tracking if hash was
already referenced.

IMHO, nearly always the approach taken by String.hashCode() suffices:
Zero means either that the result wasn't computed yet, or that you
were unlucky enough to get 0 as a result. Unlucky because it means
that the value gets computed again and again. Fortunately, it's quite
improbable and so taking the risk is better than spending 4 or 8 bytes
(needed for a boolean considering the alignment). I'm not sure if
there are situations where you need to avoid the risk.

I have a solution for this problem.  The JVM keeps the list of modifiers for each variable, method, and class in memory variables.  So, when a lazy variable is referenced, the JVM simply checks its modifier list.  If it shows as lazy, it then initializes it by what ever means is setup for the purpose.  Then, it removes the lazy modifier from the memory variable associated with this variable, thereby making this variable just an ordinary final variable.  So, after it has been initialized, the copy in memory will be as though it was:
    public final int hash;
and would be treated as such until the class instance is discarded.  In the JVM, these modifiers are stored as bits in an int.  So the JVM would just flip the lazy bit to off, and no more lazy variable.  Simple!




PS: The above hashCode doesn't make much sense, you probably meant
"int h = id" on the first line.

Here's another thought.  Since all this is to make life easier, how about this:
    public final lazy int hash;
 public final lazy boolean done;
No explicit method in the field's declaration.  Using the method declaration and naming convention already stated, you could use either of the following method types:

    private lazy int hash(){
        int h = id;
        h = 31 * h + name.hashCode();
        return h;
    }
    public final lazy void setDone(){
        done = true;
    }
With hash the method is private, so it uses the variable name as the method name.  The "hash = hash()", would be implied. 

But with done, the method is public, hence, it is set as final lazy void and uses the setXXXX() naming convention.  The compiler (javac) would check to make sure that the instance variable done, in this case (setDone()), is set, in a similar way it checks for a return value.  Again, once the variable has been set, its lazy flag would be turned off, preventing further modification of done.

BradW

unread,
Aug 5, 2011, 9:30:01 PM8/5/11
to java-language...@googlegroups.com

A further thought.  In the case of done, where it has no implicit private method, such as:

     private lazy boolean done(){...}

if it is referenced before it has been initialized, I think it would be appropriate to have an exception thrown: UninitializedFinalLazyVariableException, or something like that.

BradW

unread,
Aug 5, 2011, 9:49:42 PM8/5/11
to java-language...@googlegroups.com
What do you think about this use-case?:

    private final lazy ImmutableData data;

    public final lazy void setData(Data data){
        this.data = data.asImmutable();
    }

Should this be allowed?  Setting the value of a final lazy variable to some externally supplied value?  Or should it be limited to something internal to the class, as previously documented?
To understand this, you will need to get the code for the library and the sample application.  Both are available from the project site: http://java.net/projects/jdk-immutability/downloads , or see the MakeImmutable interface in the online Javadocs: http://jdk-immutability.java.net/JDKImmutable/0.1/javadoc/index.html.

Maaartin G

unread,
Aug 5, 2011, 9:53:06 PM8/5/11
to Java Language Specification
On Aug 6, 3:19 am, BradW <b...@willcott.com> wrote:
> On Friday, August 5, 2011 10:37:51 AM UTC+8, Maaartin G wrote:
> has the *lazy* modifier to designate it to be the init method for the *final
> * *lazy hash* variable. The naming is specific.  Note that this is *private*,
> and uses the actual variable name, because it is declared above as the
> field's initializer method: hash = hash();.  This keeps it simple.  No
> ambiguity.

I can't see the simplicity here, probably I'm missing something.

Nor can I see any ambiguity in my proposal. I'd say it's as simply as
possible:
- no explicit field declaration needed
- there's one private field created implicitly, it's name doesn't
matter
- only the method needs to be declared (and methods are better then
fields)

> I have a solution for this problem.  The JVM keeps the list of modifiers for
> each variable, method, and class in memory variables.

It only keeps them once per class.

> So, when a *lazy*variable is referenced, the JVM simply checks its modifier list.  If it
> shows as *lazy*, it then initializes it by what ever means is setup for the
> purpose.  Then, it *removes* the *lazy* modifier from the memory variable
> associated with this variable, thereby making this variable just an ordinary
> *final* variable.  So, after it has been initialized, the copy in memory
> will be as though it was:
>
>     public final int hash;
>
> and would be treated as such until the class instance is discarded.  In the
> JVM, these modifiers are stored as bits in an int.  So the JVM would just
> flip the *lazy* bit to *off*, and no more *lazy* variable.  Simple!

Simple, but works for statics only.

>     public final lazy boolean done;
>
>     public final lazy void setDone(){
>         done = true;
>     }

I actually don't get the whole idea with "done" at all. For the object
to be really immutable, you need to make sure that "setDone()" gets
called before the first access to "done". Do you agree? If so, what is
the point of "setDone" being public? If not, ... no idea.

On Aug 6, 3:30 am, BradW <b...@willcott.com> wrote:
> On Saturday, August 6, 2011 9:19:28 AM UTC+8, BradW wrote:

> A further thought.  In the case of *done*, where it has no implicit *private
> * method, such as:
>
>      private lazy boolean done(){...}
>
> if it is referenced before it has been initialized, I think it would be
> appropriate to have an exception thrown: *
> UninitializedFinalLazyVariableException*, or something like that.

I see, but this way you introduce some state visible to the outside.
You can't observe different values of done, nonetheless the state of
the object changes. IMHO, this leads to all the problems you get with
mutable object in concurrent programming.

Morten Hattesen

unread,
Aug 6, 2011, 6:32:30 AM8/6/11
to java-language...@googlegroups.com
+1 on the concept of only declaring the method as "lazy", and the VM maintaining an implicit field (and some sort of initialization flag - only requires a single bit when maintained by the VM itself).

This provides by far the simplest usage scenario, and the "principle of least surprise". First call invokes the method, subsequent calls returns the cached result.

I really don't like the "magic names", i.e. a relationship between a field and a method that is defined by a naming convention, like I have never liked the "property accessor" methods of Java being "setXxx()", "getXxx()", "isXxx()", whereas C# has an explicitly declared relation. One problem with the method prefix naming convention being that it completely blows away the concept of internationalization identifiers that is otherwise supported by Java (e.g. Chinese ideograms allowed for identifiers), which look funny with "set", "set", "is" prefix.

Morten

Maaartin G

unread,
Aug 6, 2011, 10:10:08 AM8/6/11
to Java Language Specification
On Aug 6, 12:32 pm, Morten Hattesen <morten.hatte...@gmail.com> wrote:
> This provides by far the simplest usage scenario, and the "principle of
> least surprise". First call invokes the method, subsequent calls returns the
> cached result.

Moreover, for an immutable class it works exactly like without "lazy",
just faster.

> I really don't like the "magic names", i.e. a relationship between a field
> and a method that is defined by a naming convention, like I have never liked
> the "property accessor" methods of Java being "setXxx()", "getXxx()",
> "isXxx()", whereas C# has an explicitly declared relation. One problem with
> the method prefix naming convention being that it completely blows away the
> concept of internationalization identifiers that is otherwise supported by
> Java (e.g. Chinese ideograms allowed for identifiers), which look funny with
> "set", "set", "is" prefix.

Translating "get" and "set" looks extremely silly to me. In order for
this to make sense you'd need to translate all the standard classes as
well. Moreover, there may be different translation for the prefixes
leading to confusion. It could get even more funny in an international
company.

The only non-English identifiers I use are domain-specific names (here
the translation would be counterproductive, and possibly ambiguous). I
use words composed of words of English and other language and it seems
quite natural to me.

BradW

unread,
Aug 6, 2011, 4:18:14 PM8/6/11
to java-language...@googlegroups.com
Have you guys looked at my sample app (HRMLite) and RI library (JDKImmutable)?

I will have to investigate the modifier flag variable situation you mentioned, and get back to you.

When you do look at my code, you will find an alternative to immutable, Sealable.  This is not meant
to replace immutable, but, is a complimentary interface.  It would use a final lazy field to store the
state as:

private final lazy boolean sealed;

public final lazy setSealed(){
    sealed = true;
}


public final void checkSeal() {
    if (sealed) {
        throw new SealedOperationException();
    }
}


The default value being false.  All methods that can modify the contents of a Sealable class instance,
would need to check this variable first, by calling
isSealed(), throwing an exception when it is true
This gives the programmer a class instance they can work on, until they have all the data/changes they require,
before effectively making that instance, sealed.  To all practical purposes, the instance would be immutable
The main difference, is that the immutability is not enforced, as it would be with the immutable keyword.

I disagree with the idea of not defining the variable, as in the suggestion of the implicit field creation.  This would
setup major confusion, because it would be difficult to then reference that field.  My suggestions provide ways of
clearly defining both the fields and their initializing methods.

If I'm allowed to take one step back, I would suggest that the following would also work:

public final lazy int hash = makeBrownies();

private lazy int
makeBrownies(){
    int h = id;
    h = 31 * h + name.hashCode();
    return h;

}

Divorcing the method name from the field name.  Not that I'm suggesting that "makeBrownies" is an appropriate method name in this case.
But it makes the point, I think.

As another idea.  I don't see why final lazy variables should be restricted to immutable classes.  As in my Sealable interface implementation,
AbstractSealable.  So, I see there being situations where all the method types I have suggested so far, could be used, outside of the
immutable class type.

Check out my various AbstractSealable* and Sealable* class implementations in the package: net.java.util.

Morten Hattesen

unread,
Aug 6, 2011, 5:23:26 PM8/6/11
to java-language...@googlegroups.com
Translating "get" and "set" looks extremely silly to me. In order for
this to make sense you'd need to translate all the standard classes as
well. Moreover, there may be different translation for the prefixes
leading to confusion. It could get even more funny in an international
company.

I agree totally. "set", "get" and "is" should NOT be translated/internationalized, which I have never advocated. What I claim is that the java bean naming convention should never have seen the light of day. Java should have supported first-class-properties from day one to prevent relying on method naming conventions to link fields with methods. I don't even think this is a very contentious opinion. Have a look at C# properties for a way to implement first class properties in a type-safe and unambiguous way.
 
The only non-English identifiers I use are domain-specific names (here
the translation would be counterproductive, and possibly ambiguous). I
use words composed of words of English and other language and it seems
quite natural to me.

I have always worked in organisations where the coding guidelines have been to use English (or US English) language identifiers wherever possible, so it has never been an issue for me, and I would never advocate the use of non-english language identifiers. But since Java allows any Unicode letter to be used for identifiers, and prides itself of its international/Unicode support, the Java Bean Spec (naming convention) should enforce English language method prefixes, which defeats the whole purpose of having inernatiionalizable method names in the first place.


Mind you, this is a derail of the "lazy" spec, which in itself is a slight derail of the core subject of this thread (immutable class modifier), so I'll rest my case.

Morten

Morten Hattesen

unread,
Aug 6, 2011, 5:30:32 PM8/6/11
to java-language...@googlegroups.com
I still don't see the need for the lazy modifier on the hash field.
Your example:

public final lazy int hash = makeBrownies();

private lazy int 
makeBrownies(){
    ...
}

Might as well be written as:

public final int hash = makeBrownies();

private lazy int 
makeBrownies(){
    ...
}

With the VM ensuring that subsequent calls to makeBrownies() would not cause a method invocation but simply return the (implicitly cached) value obtained from the first invocation.

BradW

unread,
Aug 6, 2011, 7:13:07 PM8/6/11
to java-language...@googlegroups.com
On Sunday, August 7, 2011 5:30:32 AM UTC+8, morten hattesen wrote:
I still don't see the need for the lazy modifier on the hash field.
Your example:

public final lazy int hash = makeBrownies();

private lazy int 
makeBrownies(){
    ...
}

Might as well be written as:

public final int hash = makeBrownies();

private lazy int 
makeBrownies(){
    ...
}

The problem here, is that the compiler default op for a final var won't allow this to happen.  Also, it breaks everyone's understanding of what it means for a var to be final.  By using an additional keyword, such as lazy, people will know that this is not a standard final var.  Further, by defining the var with initialization method, it removes any ambiguity, and provides great flexibility in how the var's value is determined.

BradW

unread,
Aug 6, 2011, 7:28:46 PM8/6/11
to java-language...@googlegroups.com


On Sunday, August 7, 2011 5:23:26 AM UTC+8, morten hattesen wrote:
I agree totally. "set", "get" and "is" should NOT be translated/internationalized, which I have never advocated. What I claim is that the java bean naming convention should never have seen the light of day. Java should have supported first-class-properties from day one to prevent relying on method naming conventions to link fields with methods. I don't even think this is a very contentious opinion. Have a look at C# properties for a way to implement first class properties in a type-safe and unambiguous way.
 
Briefly, I agree with you on this.  I prefer to use public vars whenever possible.  It would be nice to have the C# type of properties.  Purhaps we should start a new discussion topic on this?

Mind you, this is a derail of the "lazy" spec, which in itself is a slight derail of the core subject of this thread (immutable class modifier), so I'll rest my case.

The "lazy" spec is in my opinion an integral part of the immutable class modifier discussion.  It has come out of the ongoing discussions on this topic, to solve problems like the hash var in java.lang.String.  As part of this discussion, I have proposed an expanded use of the lazy modifier, beyond a purely immutable class use.  If you think it necessary, I could start a separate topic on this expanded use aspect?


BradW

unread,
Aug 6, 2011, 8:32:38 PM8/6/11
to java-language...@googlegroups.com
I have just found this blog on this topic:

Immutability in C# Part One: Kinds of Immutability

Obviously, immutability has been discussed many times, and I suspect even in relation to Java.  What I don't understand, is why nothing has been done about.  The benefits of immutability are many, with few, if any, cons.  What's the hold-up?

The similarity between the above linked blog and my own thoughts and ideas are uncanny.  If I'd known about the blog before, I could have started with it, and then built on it.  Ah well, better late than never.

If I wasn't so anti-MS, I'd consider C# as an alternative to Java.  But, I'm committed to Java and its improvement as the primary development language of the Internet, desktop and server.  So, lets get to it guys.

I want to see a JDK 1.7.1 release with a number extras, immutability (immutable and lazy), just the beginning!

Maaartin G

unread,
Aug 7, 2011, 4:56:07 AM8/7/11
to Java Language Specification
On Aug 6, 10:18 pm, BradW <b...@willcott.com> wrote:
> I disagree with the idea of *not* defining the variable, as in the
> suggestion of the *implicit* field creation.  This would
> setup major confusion, because it would be difficult to then reference that
> field.  My suggestions provide ways of
> clearly defining both the fields and their initializing methods.

There would be no confusion at all since nobody is supposed to access
the variable ever. The point of "public lazy hashCode()" is to
override Object.hashCode(), that's the most important part. For
efficiency reasons, the value gets cached using some variable. I'm
never gonna access the variable myself, so I don't care what it's
name. Nobody can ever need it since its value can't be written and
reading it results the same value as the call of the method.

On Aug 7, 1:28 am, BradW <b...@willcott.com> wrote:
> Briefly, I agree with you on this.  I prefer to use *public* vars whenever
> possible.

It seems like you're doing something wrong.
Reply all
Reply to author
Forward
0 new messages