From: markspace on
Lew wrote:

> The field in question is private, and does not change the externally
> observable state. So the String instance acts like it's immutable, but
> has mutable internal state.
>
> So in a real sense String is mutable, and just as real, it's immutable.


To expound on this a bit, final fields in a constructor are treated
specially by the JVM and JLS. Even if an entire class is not strictly
immutable, the values and objects referred to by final fields will be
treated as immutable by the compiler & runtime.

Thus, if you have your own class which follows the rules for immutablity
for some of its fields, those fields will also be treated as immutable &
safe for publication with a data race.

public class Stooges {
private final List<String> stooges;
private int count;

public Stooges {
stooges = new ArrayList<String>();
stooges.add("Lary");
stooges.add("Curly");
stooges.add("Moe");
}

public boolean isStooge( String name ) {
return stooges.contains( name );
}

public int size() {
if( count == 0 ) {
count = stooges.size();
}
return count;
}
}

The field "stooges" is immutable and treated as such by the JVM. The
fact that "count" is kind of lazily-immutable (*) still is thread safe;
this whole class can be treated as immutable, not as effectively
immutable, with no repercussions or harm done.

(*) Is there an actually name for "lazily-immutable?" I seem to
remember it being talked about in JCIP but I can't find a reference now.


Hmmm, I wonder if a class can have no final fields, have at least one
mutable private field and still be immutable.
From: Lew on
On Jul 21, 4:09 pm, markspace <nos...(a)nowhere.com> wrote:
> Lew wrote:
> > The field in question is private, and does not change the externally
> > observable state.  So the String instance acts like it's immutable, but
> > has mutable internal state.
>
> > So in a real sense String is mutable, and just as real, it's immutable.
>
> To expound on this a bit, final fields in a constructor are treated
> specially by the JVM and JLS.  Even if an entire class is not strictly
> immutable, the values and objects referred to by final fields will be
> treated as immutable by the compiler & runtime.
>
> Thus, if you have your own class which follows the rules for immutablity
> for some of its fields, those fields will also be treated as immutable &
> safe for publication with a data race.
>
> public class Stooges {
>    private final List<String> stooges;
>    private int count;
>
>    public Stooges {
>      stooges = new ArrayList<String>();
>      stooges.add("Lary");
>      stooges.add("Curly");
>      stooges.add("Moe");
>    }
>
>    public boolean isStooge( String name ) {
>      return stooges.contains( name );
>    }
>
>    public int size() {
>      if( count == 0 ) {
>        count = stooges.size();
>      }
>      return count;
>    }
>
> }
>
> The field "stooges" is immutable and treated as such by the JVM.  The
> fact that "count" is kind of lazily-immutable (*) still is thread safe;
> this whole class can be treated as immutable, not as effectively
> immutable, with no repercussions or harm done.
>

Still, it's better most times to make something like 'count' final.
The reason 'hash' wasn't final in 'String' was the ubiquity of
'String' measured against its likely usage, making the possible
speedup likely to be worthwhile. Nearly no custom classes will have
the dynamic to justify lazy-loading for the attributes one considers
loading lazily.

public class Stooges {
private final Set <String> stooges;
private final int count;

public Stooges {
HashSet <String> sts = new HashSet <String> ();
sts.add( "Lary" );
sts.add( "Curie" );
sts.add( "Moo" );
stooges = Collections.unmodifiableSet( sts );
count = stooges.size();
}

public boolean isStooge( String name ) {
return stooges.contains( name );
}

public int size() {
return count;
}
}

--
Lew
From: markspace on
Lew wrote:

> Still, it's better most times to make something like 'count' final.


Righto. My use of count was just an example, not best practice.


> stooges = Collections.unmodifiableSet( sts );


Part of my point was that a line like this is 100% unneeded. The JLS
considers "stooges" to be unmodifiable just based on the fact that it is
never modified.
From: Lew on
Lew wrote:
>> stooges = Collections.unmodifiableSet( sts );

markspace wrote:
> Part of my point was that a line like this is 100% unneeded. The JLS
> considers "stooges" to be unmodifiable just based on the fact that it is
> never modified.

Until someone modifies the class later by, for example, adding method
'public Set <String> getStooges()'.

Could you cite the particular part of the JLS to which you refer here, please?

--
Lew
From: John B. Matthews on
In article <i27k65$lse$1(a)news.eternal-september.org>,
markspace <nospam(a)nowhere.com> wrote:

> (*) Is there an actually name for "lazily-immutable?" I seem to
> remember it being talked about in JCIP but I can't find a reference
> now.

Is this what you mean? "A blank final is a final variable whose
declaration lacks an initializer."

<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.12.4>

--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>