Java's immutability isn't solid

Sorry, but I’ve become sick of using the keyword ‘final’ all over the place so I figured that I only have to use it once and then I can delegate an object anywhere and everywhere throughout my program, without the worry of the “new” keyword.

Or so it may seem.
http://members.optusnet.com.au/ksaho/something/test.jar

Source code is in the jar file as well.
I will explain what’s going on.

I have created 5 classes.
[i]The main class creates an object called “ObjA” with an index value of 1.

The main class creates an object called “DelegateA” after ObjA is created.

ObjA is called “obj” and it’s a “final”(immutable) object, and is sent into DelegateA’s constructor.

DelegateA creates a new object called DelegateB and send obj into DelegateB’s constructor.

DelegateB creates an object called “Modd” and send obj into it’s contructor.

Modd then proceeds to reinstance obj by calling “obj = new ObjA(-1);”.[/i]

The change is recognised within the Modd object but isn’t recognised within Main.
However the same behaviour occurs wheather or not the object is declared immutable within the Main class.

Sorry if you guys have discussed this 10 years ago, but I’ve just found this out.
Personally I see this as a problem because if an object is declared immutable, it should remain immutable wherever it may go.
The current behaviour does not do this, and can introduce bugs and incompatibilities into your application.
If you wrote your app to be extensible and a class passes an immutable object, the mere fact that you can create a new instance from it can cause issues within your program.

The second issue is that even if a superclass declares the object to be immutable in it’s constructor, a subclass doesn’t recognise this and makes an assumption that the object is mutable.
Either Sun has created a giant boom boom, or I may have created an error in my program and a lack of caffeine has caused me to jump one ship too far. :slight_smile:

Also I just want to point out in Sun’s words, what an immutable object or vairable is.
I’ve also tested my program with primitive types and the same behaviour occurs.

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/finalVariables.html

Remember that Java passes all arguments by value. For objects, the value of the reference is passed.

errrrr, the behaviour your program demonstrates is in perfect accordance with the Java spec.

When you pass an Object as a parameter, all you are passng is a copy of the reference to that Object. (not a pointer to the reference, or the Object itself)

Therefor a method which alters where any of its parameters point, will have no effect on any other references.

Simplifying your example :-


public static void doesNothing(String s)
{
   s = "b";
}

public static void main(String [] args)
{
   final String str = "a";
   System.out.println(str);
   doesNothing(str);
   System.out.println(str);
}

The above code will print “a” twice, as a copy of the reference is passed into doesNothing(), so reassigning it will have no effect in main().

Son-ov-a… Damn, I forgot, this isn’t C.

I can’t believe I made a mistake like this after nearly 2 years of Java programming experience.

Sometimes I should save myself the humilitation and not get out of bed. ::slight_smile:

Thanks for clearing this up guys.