Search code examples
javafinal

Passing final parameters to another method without final parameter declaration


I am reading about final variables and learnt that when you have a parameter as final, you cannot change it. But then I tried out something

Compiler complains here saying you cannot change final parameter which I can understand

public class FinalVariableTest {

    public void method1(final FinalVariableTest object){
        object = new FinalVariableTest(); //Not allowed, compiler complains
    }

    public void method2(FinalVariableTest object){
        object = new FinalVariableTest();
    }

    public static void main(String[] args) {
        FinalVariableTest test = new FinalVariableTest();
        test.method1(test);
    }
}

But the compiler is fine with this

public class FinalVariableTest {

    public void method1(final FinalVariableTest object){
        method2(object);
    }

    public void method2(FinalVariableTest object){
        object = new FinalVariableTest(); //Compiler does not complain
    }

    public static void main(String[] args) {
        FinalVariableTest test = new FinalVariableTest();
        test.method1(test);
    }
}

What is the reason behind this?


Solution

  • The keyword final means that you cannot change the reference held in the variable to another object (primitive types aside), not that you cannot change the referenced object itself.

    In your example, you cannot change what object variable in method1() is pointing at, but you can indeed change what the object variable in method2() is pointing at, since that one isn't final. And the whole time, you're free to change the object being referenced / pointed at, unless that object itself has protections against it.

    final method1.object -- cannot point elsewhere
                 \                    method2.object -- not final, can be switched to here --.
                  \                  /                                                       |
                   \                /                                                        |
               original FinalVariableTest instance                       new FinalVariableTest()