I need verfication - Java Immutable class Is this class Immutable?

Given the following class is it Immutable?

public final class BeImmutable {
      Integer myTestProperty;

      public    static int getTheNumber(  myTestProperty) {
              System.out.println("myTestProperty="+ myTestProperty);
               return (myTestProperty *myTestProperty+ 666);
    }
}

According to my current knowledge about immutable objects they must be final and all properties contained final
Integer is a final object so is this final? or must I add the final   keyword to the myTestProperty  property  to make the class truly immutable  ??

So by that rule the following is not immutable:
public final class NotImmutableEg {
private  StringBuilder sbName;
      void StringBuilder sort(StringBuilder psb)  {  return(psb);}
}
}
So would the following be immutable?
public final class NotImmutableEg {
private final  StringBuilder sbName;
    public   void StringBuilder sort(StringBuilder psb)  {  return(psb);}
}
}
/
The complete rules I gleaned were:
1. An  immutable class can not be modified after construction, any modification would result in
a new immutable class. created.

2. All fields of Immutable class must be final.
3. class must be properly constructed i.e. class reference must not leak during construction process.
4. class must be final in order to restrict sub-class for altering immutability of parent class.

What about the 3rd rule what does that mean exactly what is meant by leak??
It is said by using Immutable classes Threading is easier due to less need for sychronized methods and control blocks of code.
LVL 2
Robert SilverSr. Software EngineerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

krakatoaCommented:
If you haven't already done so, then look at the lit on this here.

It explains things to look out for, which are the types of things you are concerned about.  This is from the lit, so it's not "just another" link.
0
dpearsonCommented:
Technically an immutable class is simply one where the data cannot be changed.

So this class as written today:
public final class BeImmutable {
      private Integer myTestProperty;

      public BeImmutable(Integer value) { myTestProperty = value ; }

      public    static int getTheNumber(  myTestProperty) { 
              System.out.println("myTestProperty="+ myTestProperty);
               return (myTestProperty *myTestProperty+ 666);
    }
}

Open in new window


is actually immutable - simply because there is no way to modify the state (myTestProperty) after construction.
(I added a constructor and the keyword 'private' to the member - so nothing else in the package can sneak in and access it).

However, while it's immutable, it's usually considered poor practice to make a class immutable without making the members final, because I could easily come along tomorrow and add a method:

setProperty(Integer newValue) { myTestProperty = newValue ; }

and now the class is no longer immutable.

If the member variables are marked as 'final', that would produce a compile time error and it'll be clearer that my original intention was to make this class immutable.

So this is the real rule:
"1. An  immutable class can not be modified after construction, any modification would result in
a new immutable class. created."

and these are some helpful tips you can use to create an immutable class, but it's not the only valid way:
"2. All fields of Immutable class must be final.
3. class must be properly constructed i.e. class reference must not leak during construction process.
4. class must be final in order to restrict sub-class for altering immutability of parent class."

To answer your question about #3.  This is code that leaks a reference during construction:

public class Leaker {
    private final Integer myValue ;

    public Leaker() {
        myValue  = 7 ;
        updateLeaker(this) ;
    }

    public static void updateLeaker(Leaker leaker) {
        // The leaker object passed here is accessible before the constructor has completed execution
        // That's a no-no
    }
}

Open in new window


This is considered bad because the Java compiler is allowed to produce code that is incorrect in this situation, especially in multi-threaded environments.  You're not meant to access an object until its fully constructed and this code violates that rule.

Hope that helps explain things,

Doug
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Robert SilverSr. Software EngineerAuthor Commented:
Yes that makes sense but what if you change
public static void updateLeaker(Leaker leaker) {

to
public static synchronized void  updateLeaker(Leaker leaker) {
        // The leaker object passed here is accessible before the constructor has completed execution
        // That's a no-no ???
    }

Still thank you for that explanation. It was very clear and helpful.
0
dpearsonCommented:
I think even this code is technically illegal:

public static synchronized void  updateLeaker(Leaker leaker) {
        // The leaker object passed here is accessible before the constructor has completed execution
        // That's a no-no ???
    }

The issue is that this thing about "not leaking access to an object before the constructor completes" is part of the rules written right into the Java memory model - which defines what the guarantees are about when objects are visible to other threads (on other processors).  The issues arise because the compiler is allowed to make certain optimizations around the behavior of the processor cache (which if you think about isn't shared memory - 2 CPUs each have their own unique caches, unlike main memory which is shared).  I'm not someone who caries around a copy of the Java language spec in my back pocket - but the people who do could no doubt point you to the right section :)

Now in practice if you add a "synchronized" statement it's hard to imagine any compiler will actually produce code that's invalid.  That's because "synchronized" itself triggers a requirement that instructions executed before it must be visible to all threads executing code after it - so in some sense the objects that exist before it should be 'published' to all threads.  But doing this is playing with fire.  You're still violating a rule and if your code malfunctions in odd ways in a multi-processor environment and you submit a bug on it, the JVM guys can say "well...that's because your code is illegal".

Simple answer is that's it's best to avoid this.  And honestly code that waits to call methods until after the constructor is finished is better code anyway.

Incidentally easily the most common examples of violating this is the old example of how to make a thread:

public class MyThread extends Thread {
     public MyThread() {
        ...
        // This is technically wrong, because it starts the thread before the constructor finishes
        start() ;
     }
}

You can probably find that code in 100 old tutorials on threads.

Anyway, these days we use Executors, so no reason to ever be newing up Thread objects directly...but just thought I'd mention it :)

Doug
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.