Why mutable/immutable can't be valid class qualifier?

H

hiwa

I used to be uneasy at the fact that immutability
of a class object is only casually mentioned in
some tiny corner of the API documentation.

And I wonder why we can't do:

public immutable class BigDecimal

or, implementing a marker inteface:

public class BigDecimal
All Implemented Interfaces:
Immutable, Serializable, Comparable<BigDecimal>
 
E

Eric Sosman

hiwa wrote On 03/07/06 04:36,:
I used to be uneasy at the fact that immutability
of a class object is only casually mentioned in
some tiny corner of the API documentation.

And I wonder why we can't do:

public immutable class BigDecimal

or, implementing a marker inteface:

public class BigDecimal
All Implemented Interfaces:
Immutable, Serializable, Comparable<BigDecimal>

Probably because "immutable" can be hard to pin down
satisfactorily. Example:

final class ImmutableThing {

// these members are assumed immutable, too:
private final SomeThing x;
private final OtherThing y;
private final ThirdThing z;

ImmutableThing() {
x = new SomeThing("surprise");
y = new OtherThing("fear");
z = new ThirdThing("there is no third thing");
}

public boolean equals(Object obj) {
if (! (obj instanceof ImmutableThing))
return false;
ImmutableThing that = (ImmutableThing)obj;
return x.equals(that.x) && y.equals(that.y)
&& z.equals(that.z);
}

private int lazyHash; // computed only if needed

public int hashCode() {
if (lazyHash == 0) {
// do the expensive hashing only once
laxyHash = x.hashCode() ^ y.hashCode()
^ z.hashCode();
}
return lazyHash;
}
}

The crucial question: Is this class immutable? One
argument says it's not, because the lazyHash member's value
can change after construction. Another argument says that
doesn't matter, because lazyHash can only be observed by
calling hashCode() and hashCode() returns a constant value.
Both are right, in their own terms -- and how are you going
to define the semantics of a keyword or marker interface so
as to make both sides happy? If you can't, how will you
placate those on the unhappy side?

There's quite a lot about Java that lives solely in the
documentation. For instance, the compiler would accept

class Stupid implements Comparable {
public int compareTo(Object obj) {
return 42;
}
}

Only the JavaDoc tells us that this does not fulfill the
contract of the Comparable interface; the compiler is not
aware of the contract and so cannot enforce it. Immutabilty
(both the quality itself and the sense in which it is to be
understood for the class at hand) is a similar case. Or as
a colleague once observed, "The compiler is not a substitute
for self-discipline."
 
O

Oliver Wong

Eric Sosman said:
Probably because "immutable" can be hard to pin down
satisfactorily. Example:

final class ImmutableThing {

// these members are assumed immutable, too:
private final SomeThing x;
private final OtherThing y;
private final ThirdThing z;

ImmutableThing() {
x = new SomeThing("surprise");
y = new OtherThing("fear");
z = new ThirdThing("there is no third thing");
}

public boolean equals(Object obj) {
if (! (obj instanceof ImmutableThing))
return false;
ImmutableThing that = (ImmutableThing)obj;
return x.equals(that.x) && y.equals(that.y)
&& z.equals(that.z);
}

private int lazyHash; // computed only if needed

public int hashCode() {
if (lazyHash == 0) {
// do the expensive hashing only once
laxyHash = x.hashCode() ^ y.hashCode()
^ z.hashCode();
}
return lazyHash;
}
}

The crucial question: Is this class immutable? One
argument says it's not, because the lazyHash member's value
can change after construction. Another argument says that
doesn't matter, because lazyHash can only be observed by
calling hashCode() and hashCode() returns a constant value.
Both are right, in their own terms

Excellent example. Here's another one which shows why a class which may
appear to be immutable to the compiler, but appears to NOT be immutable to
the user.

<pseudocode>
class FakeImmutable {
private final FileWriter out;
private final FileReader in;

public FakeImmutable() {
File f = createTempFile("fake","immutable");
out = new FileWriter(f);
in = new FileReader(f);
}

public synchronized String getX() {
/*Read from the in, and return whatever you got.*/
}

public synchronized void setX(String newValue) {
/*Clear the file, and write the newValue to the file.*/
}
}
</pseudocode>

From the compiler's perspective, this is an immutable class. That is,
all of its fields are final (constant). But from the user's perspective, it
appears to have a field called X which is settable.

- Oliver
 
H

hiwa

Eric said:
Probably because "immutable" can
be hard to pin down satisfactorily.

Oliver said:
immutable to the compiler, but appears
to NOT be immutable to the user

Well, then, what could be the definition or criteria
Java API documentation uses when they call a class
object immutable? There must be one, not two or more.
 
O

Oliver Wong

hiwa said:
Well, then, what could be the definition or criteria
Java API documentation uses when they call a class
object immutable? There must be one, not two or more.

They mean "from the user's perspective". That is, there does not exist a
sequence of calls that the user can make so that the apparent state of the
object changes.

Note that using the definition I just gave, Eric's example is immutable,
but mine is not. The *INTERNAL* state of Eric's example changes, but the
apparent state does not. So it is immutable.

Whereas in my example, the INTERNAL state does not change, but the
apparent state does change, so my class is not immutable (even though all of
its fields are declared final).

The basic conclusion is that humans can decide whether a class is
immutable or not, but a compiler can't. That is why there isn't an
"immutable" keyword for classes.

- Oliver
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top