natG said:
I do not understand however, the paragraph you
wrote regarding aliasable and mutuable.
I probably should have used the less technical term 'sharable' instead
of 'aliasable'. I shall do that here.
If an object is both mutable and sharable, then it must be understood
by all of the code that uses the object that the object's value is
unstable; it might be affected by other code elsewhere. If the object
is shared between threads, the object's value might change even in the
middle of a statement that is using it, such that "i.equals(i)" cannot
even be guaranteed to be true.
When we work with values, we expect them to hold still. There are two
ways of guaranteeing this. Either we make value objects unsharable, or
we make them unchangeable.
It is okay to change unshared objects; for instance, there is no way
that changing the value of an int variable can possibly affect the
value of any other int variable, because ints are always copied and
never shared.
So, if we have:
int j = 2;
someScaryObject.someScaryMethod(j);
if (j == 2)
[do something]
we can be assured that the 'if' will ALWAYS be true because we only
share *copies* of the value of j. The variable itself is never shared.
The only way that the value of j will change is if we change it
ourselves.
Similarly, it is okay to share immutable objects; there is no way that
changing a String variable can possibly affect the value of any other
String variable, because you can't change the String variable in the
first place.
So, if we have:
String s = "Hello world";
someScaryObject.someScaryMethod(s);
if (s.equals("Hello world"))
[do something]
we can be assured that the 'if' will ALWAYS be true no matter who we
share the object referenced by s with, because there is no way that
anyone can mess with the value of the String object that s references.
The only way that the value of s will change is if we change it
ourselves.
Let's see if I can make a passable example as to why this is
important...
Consider a bank Account, which has a balance of type Money:
public class Account {
public Money balance;
}
[in some method somewhere]
Account acct = [get Account object from somewhere]
Money oldBalance = acct.balance;
doSomething(acct);
if (acct.balance.equals(oldBalance)
[do some interesting stuff]
When we get to the 'if' statement, we assume that the variable 'acct'
still points to the same Account object, and that it contains the
LATEST account balance. On the other hand, we assume that 'oldBalance'
contains the ORIGINAL account balance. We are assuming that if the
balance is updated, the Account object is changed but the Money object
is not.
Money is a value type; Account is not. The rules (semantics) for them
are fundamentally different.