tags:

views:

253

answers:

6

Hi,

I often encounter methods which look like the following:

public void foo(final String a, final int[] b, final Object1 c){
}

What happens if this method is called without passing it final parameters. i.e. an Object1 that is later changed (so is not declared as final) can be passed to this method just fine

+2  A: 

Java is only pass-by-value. (or better - pass-reference-by-value)

So the passed argument and the argument within the method are two different handlers pointing to the same object (value).

Therefore if you change the state of the object, it is reflected to every other variable that's referencing it. But if you re-assign a new object (value) to the argument, then other variables pointing to this object (value) do not get re-assigned.

Bozho
When you pass an object to a method is is passed by reference and can be altered within the method
Aly
no, it isn't check my update.
Bozho
@Aly: no. The *reference* is passed by value and cannot be altered within the method – only the object to which it points can.
Konrad Rudolph
+4  A: 

Java always makes a copy of parameters before sending them to methods. This means the final doesn't mean any difference for the calling code. This only means that inside the method the variables can not be reassigned. (note that if you have a final object, you can still change the attributes of the object).

Thirler
Java does not make a copy. If you change any aspect of that within the method that change is visible to the caller.
vickirk
It certainly makes a copy (there is an optimization where the compiler doesn't make a copy, when there is no difference with making a copy). However you have to keep in mind that in the case of an object. The object really only is a reference to an object. So in that case you will get a copy of the reference.
Thirler
A: 

Consider this implementation of foo():

public void foo(final String a) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.print(a);
        }
    }); 
}

Because the Runnable instance would outlive the method, this wouldn't compile without the final keyword -- final tells the compiler that it's safe to take a copy of the reference (to refer to it later). Thus, it's the reference that's considered final, not the value. In other words: As a caller, you can't mess anything up...

netzwerg
A: 

Strings are immutable, so actully you can't change the String afterwards (you can only make the variable that held the String object point to a different String object).

However, that is not the reason why you can bind any variable to a final parameter. All the compiler checks is that the parameter is not reassigned within the method. This is good for documentation purposes, arguably good style, and may even help optimize the byte code for speed (although this seems not to do very much in practice).

But even if you do reassign a parameter within a method, the caller doesn't notice that, because java does all parameter passing by value. After the sequence

  a = someObject();
  process(a);

the fields of a may have changed, but a is still the same object it was before. In pass-by-reference languages this may not be true.

Kilian Foth
+3  A: 

There is a circumstance where you're required to declare it final --otherwise it will result in compile error--, namely passing them through into anonymous classes. Basic example:

public FileFilter createFileExtensionFilter(final String extension) {
    return new FileFilter() {
        public boolean accept(File pathname) {
            return pathname.getName().endsWith(extension);
        }
    };
}

Removing the final modifier would result in compile error, because it isn't guaranteed anymore that the value is a runtime constant. Changing the value from outside the anonymous class would namely cause the anonymous class instance to behave different after the moment of creation.

BalusC