9

Possible Duplicate:
Final arguments in interface methods - what’s the point?

While trying to experiment a few things, I've ran into a problem that it's described in this page.

interface B {
    public int something(final int a);
}

abstract class C {
    public int other(final int b);
}

class A extends C implements B {

    public int something(int a) {
        return a++;
    }

    public int other(int b) {
        return b++
    }
}

Why is such feature possible? I don't know why it's possible to to make a final parameter into a non-final one by just overriding the method. Why is the final keyword ignored in a method signature? And how do I obligate sub-classes to use in their methods final variables?

Community
  • 1
  • 1
SHiRKiT
  • 1,024
  • 3
  • 11
  • 30
  • `final` is not part of the method signature. How the subclass's method implements it is of no concern to the interface. – Steve Kuo Sep 27 '11 at 16:23

7 Answers7

9

Java passes arguments to a method by value.

Therefore, no changes to a parameter can propagate back to the caller. It follows that whether or not the parameter is declared final makes absolutely no difference to the caller. As such, it is part of the implementation of the method rather than part of its interface.

What's your motivation for wanting to "obligate sub-classes to use in their methods final variables"?

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • For me it does makes difference. I don't want to my variable to be changed in the caller method. It's original value must be preserved at all costs. – SHiRKiT Sep 27 '11 at 15:03
  • 2
    it's a primitive variable; it is passed by value and is thus protected by default. Declaring an object reference final in no way protects the contents of that object from modification. – mcfinnigan Sep 27 '11 at 15:06
  • It will be preserved, because Java always make a copy of the value before passing it to the method. If the method changes the argument value, it will change a copy, and the value of the caller method will always be unaffected, whether final is used or not. – JB Nizet Sep 27 '11 at 15:07
  • Yes, I made I mistake. After working so much with objects, and therefore it passes an copy of a "pointer" of the object, I completly forgot about primitive variables and final classes, like Integer. Wheter it's a primitive value or a Final class, I don't have to worry, because the original value will be preserved. Thank you all who have answered! – SHiRKiT Sep 27 '11 at 15:36
  • 9
    "Java passes arguments to a method by value." This is only if they are primitive. Object arguments are passed pointer style, with the pointer itself being passed by value. Therefore, you can call mutator methods on an object argument (or even use reflection if you like), and the caller will see those changes. The only thing that the caller would not see is a reassignment, since you are reassigning a copy, not his copy. – Phil Jan 07 '14 at 04:55
7

Final variables are the only ones that can be used in closures. So if you want to do something like this:

void myMethod(int val) {
    MyClass cls = new MyClass() {
        @override
        void doAction() {
            callMethod(val);  // use the val argument in the anonymous class - closure!
        }
    };
    useClass(cls);
}

This won't compile, as the compiler requires val to be final. So changing the method signature to

void myMethod(final int val)

will solve the problem. Local final variable will do just as well:

void myMethod(int val) {
    final int val0;
    // now use val0 in the anonymous class
Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
7

final for a parameter only means that the value must not be changed within the method body. This is not a part of the method signature, and is not relevant to subclasses.

It should be invalid to have final parameters in interface or abstract methods, because it's meaningless.

Cephalopod
  • 14,632
  • 7
  • 51
  • 70
  • "It should be invalid to have final parameters in interface or abstract methods, because it's meaningless." Yes it should, and yes it is meaningless, but it's _not_ invalid. :-) – Phil Jan 07 '14 at 04:56
2

Java's final is not C++ const; there is no such thing as const-correctness in Java.

In Java, one achieves const-ness using immutable classes. It turns out to be quite effective because unlike C++, one cannot simply mess with memory. (You can use Field.setAccessible(true), and then use Reflection. But even that corruption-vector can be prevented by running the JVM with an appropriately configured security manager.)

Dilum Ranatunga
  • 13,254
  • 3
  • 41
  • 52
  • I presume by "really funky things" you mean "reflection"? `foo.getClass().getDeclaredField("bar").setAccessible(true)` is all you need, on a VM that doesn't care. – Phil Jan 07 '14 at 04:48
  • Only if you have no security manager enabled. On teams I lead, we always install a security manager and whitelist access violations on a case by case basis. Contrast that to C++, where it is impossible to prevent (or even detect) a library from writing junk to memory. – Dilum Ranatunga Jan 07 '14 at 17:07
  • You did say on a unsecured VM, hence, no security manager. – Phil Jan 08 '14 at 05:14
  • I see your point. Editing answer. – Dilum Ranatunga Jan 08 '14 at 08:16
1

The final keyword for arguments is not part of the method signature, and is only important for the body of the method, because Java passes all arguments by value (a copy of the value is always made for the method call).

I only use the final keyword (for arguments) if the compiler forces me to make it final, because the argument is used inside an anonymous class defined in the method.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

In Java parameters are passed by value. Whether a parameter is final or not only affects that method, not the caller. I don't see why a class needs to obligate the subtypes.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133
1

Note that final parameters have one main purpose: you can't assign new values to them.

Also note that parameters are always passed by value, thus the caller won't see any assignments to the parameter inside the method.

If you really want to force parameters to be final (in order to prevent bugs that might be introduced when reassigning a parameter accidentially), employ a code anaylzer such as checkstyle.

Thomas
  • 87,414
  • 12
  • 119
  • 157