Java 'Final' Method: What Does It Promise

Java `final` method: what does it promise?

As mentioned, final is used with a Java method to mark that the method can't be overridden (for object scope) or hidden (for static). This allows the original developer to create functionality that cannot be changed by subclasses, and that is all the guarantee it provides.

This means that if the method relies on other customizable components like non-public fields/methods the functionality of the final method may still be customizable. This is good though as (with polymorphism) it allows for partial customization.

There are a number of reasons to prevent something from being customizable, including:

  • Performance -- Some compilers can analyse and optimise the operation, especially the one without side-effects.

  • Obtain encapsulated data -- look at immutable Objects where their attributes are set at the construction time and should never be changed. Or a calculated value derived from those attributes. A good example is the Java String class.

  • Reliability and Contract -- Objects are composed of primitives (int, char, double, etc.) and/or other Objects. Not all operations applicable to those components should be applicable or even logical when they are used in the bigger Object. Methods with the final modifier can be used to ensure that. The Counter class is a good example.


public class Counter {
private int counter = 0;

public final int count() {
return counter++;
}

public final int reset() {
return (counter = 0);
}
}

If the public final int count() method is not final, we can do something like this:

Counter c = new Counter() {   
public int count() {
super.count();
return super.count();
}
}

c.count(); // now count 2

Or something like this:

Counter c = new Counter() {
public int count() {
int lastCount = 0;
for (int i = super.count(); --i >= 0; ) {
lastCount = super.count();
}

return lastCount;
}
}

c.count(); // Now double count

Why can't a final class be inherited, but a final method can be inherited?

Why can't a final class be inherited, but a final method can be inherited?

Why? Because final means different things for classes and methods.

Why does it mean different things? Because that is how the Java language designers chose to design the language!

There are three distinct meanings for the final keyword in Java.

  • A final class cannot be extended.

  • A final method cannot be overridden.

  • A final variable cannot be assigned to after it has been initialized.

Why did they decide to use final to mean different things in different contexts? Probably so that they didn't need to reserve 2 or 3 distinct keywords. (In hindsight, that might not have been the best decision. However that is debatable ... and debating it is IMO a waste of time.)

It is worth noting that other keywords have multiple meanings in Java; e.g., static and default (in Java 8).

Why an object marked as final can be modified and call non-final method in Java?

Referencing Erik's answer in comments, I found an easy explanation for C++ programmers.

Pet pet; in Java is like Pet* pet; in C++.

final Pet pet; in Java is like Pet * const pet; in C++ which makes the pointer const but not the value itself.

Note that there is a subtle difference in Java and C++.

In C++, you have to assign a value when declaring a const variable but in Java, it lets you do it later but only once.

Why is it considered good practice to mark method parameters as final?

If you mark a method parameter as final, you can't modify the parameter's value within the scope of the method:

public void xyz(final String parameter) {
parameter = "..." //compiler error!
}

Understand that the value of parameter is the reference to the object passed to the method, and not the value of the object itself.

By marking the method parameter as final, the compiler will throw an error upon compilation. This serves as a reminder that you should not modify the value of the parameter within your method.

It's considered a bad practice to modify the original parameter within your method.[1]

If the value of the parameter can change to reference another object, it might not be immediately clear what object is being referenced at any given point within the body of your method.

Consider the following:

public void xyz(String parameter) {
//Complicated logic that might span 20-30 lines.

parameter = "Joe";

//More complicated logic that might span a few lines.

//New logic being added that needs reference to the value of the parameter.
}

In a complicated method, like above, it might be difficult for a programmer to identify what object parameter references. Furthermore, if the programmer needs a reference to parameter he no longer has one.



  1. Is it a good practice to change arguments in Java

Why private method can not be final as well?

Basically, it's allowed because they didn't feel like it's worthwhile to put a special case prohibiting the private modifier. It's like how you can also declare methods on an interface as public, or nested classes in an interface as static, even though those keywords are implied in interfaces. You can also declare final methods on a final class, etc.

Java took the stance of not complaining when you add redundant modifiers. They do it consistently.

Local variable needs to be declared final

Since you're not modifying box in the outer code, using final is exactly the correct way to solve this problem. It's a promise to yourself (and to the compiler) that the value of box won't change in the enclosing scope. The compiler will tell you if you break that promise.

There is no compile time or runtime cost to using final.



Related Topics



Leave a reply



Submit