简体   繁体   中英

Final object can be modified but reference variable cannot be changed

A reference variable marked final cant reassigned to different object.The data with in object can be modified but the reference variable cannot be changed.

Based on my Understanding I have a created a code below where I am trying to reassign a new UserId of 155.As the Definition goes I am only trying to change data within the object. But the reference is same.

public class FinalClass 
{   
    public static void main(String[] args)
    {
        ChildClass objChildClass = new ChildClass(); 
        objChildClass.UserId = 155;
    }
}

class ChildClass
{
    public static final int  UserId = 145;  
}

I believe I misunderstood the above concept.

Kindly explain the same with example.

Thanks for Reply.

You can't change final value using "=" operator. If you do it, you try to change the reference (or primitive) and final states that this cannot be changed.

You can change existing object's fields:

public static final User user = NewUser(145);

    public static void main(String[] args)
    {
        user.setId(155);
    }

In your modified question, a change would get it to work, I am not sure if this is what you want.

public class FinalClass 
{   
    public static void main(String[] args)
    {
        final ChildClass objChildClass = new ChildClass(); 
        ^^^^^
        objChildClass.UserId = 155;
        //objChildClass = new ChildClass();
    }
}

class ChildClass
{
    public static int  UserId = 145;  
                ^^^
}

Now objChildClass is final, you can modify its members, but not change the object it points to. UserId is no longer final so it can be changed.

Your understanding of the concept was right. Wait I will try to explain the beauty of final keyword. i have divided it in three parts :

  1. If you are using final keyword for any member(local variable/instance variable/method) it means there is no way that you can modify the value of that particular variable(if method, that can not be over-ridden) throughout your program.
  2. If you are declaring a class as final, then, it means that no other class(in same or different package) can extend that class(final class), in other words the final class can never be subclassed, but, the final class can be used as the "Superclass reference".
  3. Third is the case which you are referring to. If any object reference variable is declared as final, then it means that the final reference variable can never ever in its entire life refer to a different object but the data within the object(the object your reference variable is referring to) can be modified.

I have written a class here hope that clarifies all the doubts you have.

public class FinalSampleTestDrive {

public static void main(String[] args) {

    final FinalSample obj = new FinalSample();

    FinalSample obj2 = new FinalSample();
    FinalSample obj3 = new FinalSample();

    obj2.setName("arya");
    System.out.println(obj2.getName());

    obj3 = obj2;  //allowed

    System.out.println(obj3.getName());

    //obj = obj2 //not allowed as obj is final and can not be modified

    obj.setName("shubham");
    System.out.println(obj.getName());

    //but the value of the instance variables, the obj is referring to
    //can change

    obj.setName("shivam");
    System.out.println(obj.getName());



}

}

and this is the FinalSample class which is getting instantiated here :

public class FinalSample {

private String name;
private String age;

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getAge() {
    return age;
}
public void setAge(String age) {
    this.age = age;
}

}

You try to run it in different ways on your machine.

Happy Coding :)

int is a primitive type and not a reference to a complex type. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

UserId is of type int, which is a primitive type, therefore different rules apply than for Objects. a primitive variable is no pointer but the value itself. But even if you were using an Integer (Object type), you wouldn't be able to change its value, since the wrapper types for primitives are immutable.

I believe I misunderstood the above concept.

You got it correct, but you are not testing it correctly. If the UserId would have been a class with a id (or any name) property, then you would be able to change the values of it but not the reference.

Here you are creating a primitive type variable and not a object. Try using the wrapper class Integer for the same test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM