final variable in methods in Java [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why would one mark local variables and method parameters as “final” in Java?
I was checking some Java code, I am not good at java at least have some knowledge what final does such as sealed classes, readonly fields and non-overridable methods but this looks weird to me, declaring a variable final in methods:
private static void queryGoogleBooks(JsonFactory jsonFactory, String query) throws Exception {
// Set up Books client.
final Books books = Books.builder(new NetHttpTransport(), jsonFactory)
.setApplicationName("Google-BooksSample/1.0")
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
#Override
public void initialize(JsonHttpRequest request) {
BooksRequest booksRequest = (BooksRequest) request;
booksRequest.setKey(ClientCredentials.KEY);
}
})
.build();
Could you tell me what the meaning of final is in this context?
Here is the complete code:
http://code.google.com/p/google-api-java-client/source/browse/books-cmdline-sample/src/main/java/com/google/api/services/samples/books/cmdline/BooksSample.java?repo=samples

It simply makes the local variable books immutable. That means it will always be a reference to that same Book object being created and built, and cannot be changed to refer to another object, or null.
The Book object itself is still mutable as can be seen from the sequence of accessor calls. Only the reference to it is not.

In this case, final Books books simply means that books must be assigned a value exactly once.
I like to use the final keyword like this as it shows intent of the variable, which I find to be valuable information when looking at code as it removes yet another variable from the situation...so to speak.
If I don't mark a variable as final then it stands out as something to keep my eye on because it's going to change values sometime soon. This information is helpful while, for example, stepping through the code in the debugger or refactoring & moving around code.
For further reading on all things final: The Final Word On the final Keyword

This likewise makes the variable reference read-only. Usually, this is to protect the code from accidentally modifying a variable that must not change.

I'm pretty sure it means nothing more than the variable books cannot be overwritten later on in the method.

This code is using anonymous class JsonHttpRequestInitializer, where it refers to the local variable in method queryGoogleBooks, the problem in this kind of situation is that the queryGoogleBooks method could return before initialize method of the JsonHttpRequestInitializer is completed, where it could cleanup the variable and could cause the initialize method of JsonHttpRequestInitializer to fail. So it is required to declare the variables as final in this type of situations. For more details refer to,
Cannot refer to a non-final variable inside an inner class defined in a different method

Related

why should we use final to mark the constructor parameter in enum? [duplicate]

I can't understand where the final keyword is really handy when it is used on method parameters.
If we exclude the usage of anonymous classes, readability and intent declaration then it seems almost worthless to me.
Enforcing that some data remains constant is not as strong as it seems.
If the parameter is a primitive then it will have no effect since the parameter is passed to the method as a value and changing it will have no effect outside the scope.
If we are passing a parameter by reference, then the reference itself is a local variable and if the reference is changed from within the method, that would not have any effect from outside of the method scope.
Consider the simple test example below.
This test passes although the method changed the value of the reference given to it, it has no effect.
public void testNullify() {
Collection<Integer> c = new ArrayList<Integer>();
nullify(c);
assertNotNull(c);
final Collection<Integer> c1 = c;
assertTrue(c1.equals(c));
change(c);
assertTrue(c1.equals(c));
}
private void change(Collection<Integer> c) {
c = new ArrayList<Integer>();
}
public void nullify(Collection<?> t) {
t = null;
}
Stop a Variable’s Reassignment
While these answers are intellectually interesting, I've not read the short simple answer:
Use the keyword final when you want the compiler to prevent a
variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Example
Let’s see the effect in action.
Consider this simple method, where the two variables (arg and x) can both be re-assigned different objects.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Mark the local variable as final. This results in a compiler error.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Instead, let’s mark the parameter variable as final. This too results in a compiler error.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Moral of the story:
If you want to ensure a variable always points to the same object,
mark the variable final.
Never Reassign Arguments
As good programming practice (in any language), you should never re-assign a parameter/argument variable to an object other than the object passed by the calling method. In the examples above, one should never write the line arg = . Since humans make mistakes, and programmers are human, let’s ask the compiler to assist us. Mark every parameter/argument variable as 'final' so that the compiler may find and flag any such re-assignments.
In Retrospect
As noted in other answers…
Given Java's original design goal of helping programmers to avoid dumb mistakes such as reading past the end of an array, Java should have been designed to automatically enforce all parameter/argument variables as 'final'. In other words, Arguments should not be variables. But hindsight is 20/20 vision, and the Java designers had their hands full at the time.
So, always add final to all arguments?
Should we add final to each and every method parameter being declared?
In theory, yes.
In practice, no.➥ Add final only when the method’s code is long or complicated, where the argument may be mistaken for a local or member variable and possibly re-assigned.
If you buy into the practice of never re-assigning an argument, you will be inclined to add a final to each. But this is tedious and makes the declaration a bit harder to read.
For short simple code where the argument is obviously an argument, and not a local variable nor a member variable, I do not bother adding the final. If the code is quite obvious, with no chance of me nor any other programmer doing maintenance or refactoring accidentally mistaking the argument variable as something other than an argument, then don’t bother. In my own work, I add final only in longer or more involved code where an argument might mistaken for a local or member variable.
#Another case added for the completeness
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}
record
Java 16 brings the new records feature. A record is a very brief way to define a class whose central purpose is to merely carry data, immutably and transparently.
You simply declare the class name along with the names and types of its member fields. The compiler implicitly provides the constructor, getters, equals & hashCode, and toString.
The fields are read-only, with no setters. So a record is one case where there is no need to mark the arguments final. They are already effectively final. Indeed, the compiler forbids using final when declaring the fields of a record.
public record Employee( String name , LocalDate whenHired ) // 🡄 Marking `final` here is *not* allowed.
{
}
If you provide an optional constructor, there you can mark final.
public record Employee(String name , LocalDate whenHired) // 🡄 Marking `final` here is *not* allowed.
{
public Employee ( final String name , final LocalDate whenHired ) // 🡄 Marking `final` here *is* allowed.
{
this.name = name;
whenHired = LocalDate.MIN; // 🡄 Compiler error, because of `final`.
this.whenHired = whenHired;
}
}
Sometimes it's nice to be explicit (for readability) that the variable doesn't change. Here's a simple example where using final can save some possible headaches:
public void setTest(String test) {
test = test;
}
If you forget the 'this' keyword on a setter, then the variable you want to set doesn't get set. However, if you used the final keyword on the parameter, then the bug would be caught at compile time.
Yes, excluding anonymous classes, readability and intent declaration it's almost worthless. Are those three things worthless though?
Personally I tend not to use final for local variables and parameters unless I'm using the variable in an anonymous inner class, but I can certainly see the point of those who want to make it clear that the parameter value itself won't change (even if the object it refers to changes its contents). For those who find that adds to readability, I think it's an entirely reasonable thing to do.
Your point would be more important if anyone were actually claiming that it did keep data constant in a way that it doesn't - but I can't remember seeing any such claims. Are you suggesting there's a significant body of developers suggesting that final has more effect than it really does?
EDIT: I should really have summed all of this up with a Monty Python reference; the question seems somewhat similar to asking "What have the Romans ever done for us?"
Let me explain a bit about the one case where you have to use final, which Jon already mentioned:
If you create an anonymous inner class in your method and use a local variable (such as a method parameter) inside that class, then the compiler forces you to make the parameter final:
public Iterator<Integer> createIntegerIterator(final int from, final int to)
{
return new Iterator<Integer>(){
int index = from;
public Integer next()
{
return index++;
}
public boolean hasNext()
{
return index <= to;
}
// remove method omitted
};
}
Here the from and to parameters need to be final so they can be used inside the anonymous class.
The reason for that requirement is this: Local variables live on the stack, therefore they exist only while the method is executed. However, the anonymous class instance is returned from the method, so it may live for much longer. You can't preserve the stack, because it is needed for subsequent method calls.
So what Java does instead is to put copies of those local variables as hidden instance variables into the anonymous class (you can see them if you examine the byte code). But if they were not final, one might expect the anonymous class and the method seeing changes the other one makes to the variable. In order to maintain the illusion that there is only one variable rather than two copies, it has to be final.
I use final all the time on parameters.
Does it add that much? Not really.
Would I turn it off? No.
The reason: I found 3 bugs where people had written sloppy code and failed to set a member variable in accessors. All bugs proved difficult to find.
I'd like to see this made the default in a future version of Java. The pass by value/reference thing trips up an awful lot of junior programmers.
One more thing.. my methods tend to have a low number of parameters so the extra text on a method declaration isn't an issue.
Using final in a method parameter has nothing to do with what happens to the argument on the caller side. It is only meant to mark it as not changing inside that method. As I try to adopt a more functional programming style, I kind of see the value in that.
Personally I don't use final on method parameters, because it adds too much clutter to parameter lists.
I prefer to enforce that method parameters are not changed through something like Checkstyle.
For local variables I use final whenever possible, I even let Eclipse do that automatically in my setup for personal projects.
I would certainly like something stronger like C/C++ const.
Since Java passes copies of arguments I feel the relevance of final is rather limited. I guess the habit comes from the C++ era where you could prohibit reference content from being changed by doing a const char const *. I feel this kind of stuff makes you believe the developer is inherently stupid as f*** and needs to be protected against truly every character he types. In all humbleness may I say, I write very few bugs even though I omit final (unless I don't want someone to override my methods and classes). Maybe I'm just an old-school dev.
Short answer: final helps a tiny bit but... use defensive programming on the client side instead.
Indeed, the problem with final is that it only enforces the reference is unchanged, gleefully allowing the referenced object members to be mutated, unbeknownst to the caller. Hence the best practice in this regard is defensive programming on the caller side, creating deeply immutable instances or deep copies of objects that are in danger of being mugged by unscrupulous APIs.
I never use final in a parameter list, it just adds clutter like previous respondents have said. Also in Eclipse you can set parameter assignment to generate an error so using final in a parameter list seems pretty redundant to me.
Interestingly when I enabled the Eclipse setting for parameter assignment generating an error on it caught this code (this is just how I remember the flow, not the actual code. ) :-
private String getString(String A, int i, String B, String C)
{
if (i > 0)
A += B;
if (i > 100)
A += C;
return A;
}
Playing devil's advocate, what exactly is wrong with doing this?
One additional reason to add final to parameter declarations is that it helps to identify variables that need to be renamed as part of a "Extract Method" refactoring. I have found that adding final to each parameter prior to starting a large method refactoring quickly tells me if there are any issues I need to address before continuing.
However, I generally remove them as superfluous at the end of the refactoring.
Follow up by Michel's post. I made myself another example to explain it. I hope it could help.
public static void main(String[] args){
MyParam myParam = thisIsWhy(new MyObj());
myParam.setArgNewName();
System.out.println(myParam.showObjName());
}
public static MyParam thisIsWhy(final MyObj obj){
MyParam myParam = new MyParam() {
#Override
public void setArgNewName() {
obj.name = "afterSet";
}
#Override
public String showObjName(){
return obj.name;
}
};
return myParam;
}
public static class MyObj{
String name = "beforeSet";
public MyObj() {
}
}
public abstract static class MyParam{
public abstract void setArgNewName();
public abstract String showObjName();
}
From the code above, in the method thisIsWhy(), we actually didn't assign the [argument MyObj obj] to a real reference in MyParam. In instead, we just use the [argument MyObj obj] in the method inside MyParam.
But after we finish the method thisIsWhy(), should the argument(object) MyObj still exist?
Seems like it should, because we can see in main we still call the method showObjName() and it needs to reach obj. MyParam will still use/reaches the method argument even the method already returned!
How Java really achieve this is to generate a copy also is a hidden reference of the argument MyObj obj inside the MyParam object ( but it's not a formal field in MyParam so that we can't see it )
As we call "showObjName", it will use that reference to get the corresponding value.
But if we didn't put the argument final, which leads a situation we can reassign a new memory(object) to the argument MyObj obj.
Technically there's no clash at all! If we are allowed to do that, below will be the situation:
We now have a hidden [MyObj obj] point to a [Memory A in heap] now live in MyParam object.
We also have another [MyObj obj] which is the argument point to a [Memory B in heap] now live in thisIsWhy method.
No clash, but "CONFUSING!!" Because they are all using the same "reference name" which is "obj".
To avoid this, set it as "final" to avoid programmer do the "mistake-prone" code.

How is it possible to access static variables from a null reference? [duplicate]

This question already has answers here:
How come invoking a (static) method on a null reference doesn't throw NullPointerException?
(5 answers)
Closed 8 years ago.
Recently I was going through a page on javarevisited and found a block of code which asked the readers to determine what would be the output for it...
Though I got the output I am not satisfied with the result (WHICH CAME OUT TO BE "Hello") since I don't know how a static member is accessed from a null reference. What's happening in the background?
public class StaticDEMO {
private static String GREET = "Hello";
public static void main(String[] args) {
StaticDEMO demo = null;
System.out.println(demo.GREET);
// TODO code application logic here
}
}
This works because the JVM knows you are trying to access a static member on a specific class. Because you had to declare demo as a specific class (in this case a StaticDEMO), it knows to use that to find GREET.
To be clear, you don't run into this often (I actually had to type this code in to verify it, I can't say I've ever seen this). Mainly, it's good practice to always refer to static fields by their class, not an object instance (which may be null, as we can see!).
Meaning, prefer this:
System.out.println(StaticDEMO.GREET);
EDIT
I found a reference to this in the Java Specification: Chapter 15, Section 11: Field Access Expressions.
Example 15.11.1-2. Receiver Variable Is Irrelevant For static Field Access
The following program demonstrates that a null reference may be used to access a class (static) variable without causing an exception
[example not shown here for brevity]
Any method which is being decorated as static in Java means, that method is a class level memeber. That means, you do not need an object to accss static members. The static method/variable is maintained by the Class itself, and not by any instance of the class. Here in your example, the compiler already knows that the member is static member and it doesn't need any instance to access that static method.
Static members are stored with the Class, not with any specific instance of it. So, it doesn't matter that the instance is null - the member from the Class is still be accessible.
The JVM simply ignores null, because GREET is a class field and demo is irrelevant reference to refer Class field.
Static method not needed object reference to call it so you can call it even reference to the object is null.

Why is the "this" keyword final in Java? [duplicate]

This question already has answers here:
Why is assignment to 'this' not allowed in java?
(7 answers)
Closed 8 years ago.
It seems a thing that almost no one has realized, but the "this reference" in Java is final. In a normal programming day I thought I could redefine the entire instance by redefining the this reference inside the own class:
public void method() {
this = new MyObject("arg1", arg2, arg3); //it throws a compile error
}
Why the this reference is final in Java?
The problem is not that this is a final reference - it's not itself a reference at all. this is a keyword that "denotes a value that is a reference to the object for which the instance method or default method was invoked" (JLS §15.8.3).
Furthermore, it wouldn't make sense to reassign it in the sense that a variable can be reassigned. Remember that reassigning a reference changes only that reference, and not other references that might point to the same object. So reassigning this would not only be insane but also useless.
I find this question interesting from a theoretical point of view.
From a technical point of view this cannot work, as in Java we have pass-refererence-by-value ( http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html ) and cannot swap out objects where some other parts of code hold a reference to that object -- i.e. a true swap method is not possible in Java (see the linked article).
While you could theoretically reassign this, all other references to the object would not change and make the operation pretty senseless.
The closest thing you can achieve is a copy constructor.
this is not a variable you can assign a value to. It is a built-in expression returning the object that is the context for the method currently executing.
While re-assigning this might be useful for some nice hacks, it would mess up all kind of things.
The this keyword is used to provide a reference to the current object within its class. Mostly, it is used to clarify scope issues with local variables which have the same identifier as a class member. E.g.
public void function (int param) {
this.param = param
}
Reassigning it to another object goes beyond the task assigned to the keyboard. What you want to do, (reassing a reference) can be achieved on the upper context, i.e. the context in which the object was created (and a reference to it was assigned).
Wrong thinking about this. this is just a keyword(not variable) in java which referenced to current instance and its a compilation restriction that keyword(any not only this) can not be initialized.

What's the point of the "final" keyword for method arguments in Java? [duplicate]

I can't understand where the final keyword is really handy when it is used on method parameters.
If we exclude the usage of anonymous classes, readability and intent declaration then it seems almost worthless to me.
Enforcing that some data remains constant is not as strong as it seems.
If the parameter is a primitive then it will have no effect since the parameter is passed to the method as a value and changing it will have no effect outside the scope.
If we are passing a parameter by reference, then the reference itself is a local variable and if the reference is changed from within the method, that would not have any effect from outside of the method scope.
Consider the simple test example below.
This test passes although the method changed the value of the reference given to it, it has no effect.
public void testNullify() {
Collection<Integer> c = new ArrayList<Integer>();
nullify(c);
assertNotNull(c);
final Collection<Integer> c1 = c;
assertTrue(c1.equals(c));
change(c);
assertTrue(c1.equals(c));
}
private void change(Collection<Integer> c) {
c = new ArrayList<Integer>();
}
public void nullify(Collection<?> t) {
t = null;
}
Stop a Variable’s Reassignment
While these answers are intellectually interesting, I've not read the short simple answer:
Use the keyword final when you want the compiler to prevent a
variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Example
Let’s see the effect in action.
Consider this simple method, where the two variables (arg and x) can both be re-assigned different objects.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Mark the local variable as final. This results in a compiler error.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Instead, let’s mark the parameter variable as final. This too results in a compiler error.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Moral of the story:
If you want to ensure a variable always points to the same object,
mark the variable final.
Never Reassign Arguments
As good programming practice (in any language), you should never re-assign a parameter/argument variable to an object other than the object passed by the calling method. In the examples above, one should never write the line arg = . Since humans make mistakes, and programmers are human, let’s ask the compiler to assist us. Mark every parameter/argument variable as 'final' so that the compiler may find and flag any such re-assignments.
In Retrospect
As noted in other answers…
Given Java's original design goal of helping programmers to avoid dumb mistakes such as reading past the end of an array, Java should have been designed to automatically enforce all parameter/argument variables as 'final'. In other words, Arguments should not be variables. But hindsight is 20/20 vision, and the Java designers had their hands full at the time.
So, always add final to all arguments?
Should we add final to each and every method parameter being declared?
In theory, yes.
In practice, no.➥ Add final only when the method’s code is long or complicated, where the argument may be mistaken for a local or member variable and possibly re-assigned.
If you buy into the practice of never re-assigning an argument, you will be inclined to add a final to each. But this is tedious and makes the declaration a bit harder to read.
For short simple code where the argument is obviously an argument, and not a local variable nor a member variable, I do not bother adding the final. If the code is quite obvious, with no chance of me nor any other programmer doing maintenance or refactoring accidentally mistaking the argument variable as something other than an argument, then don’t bother. In my own work, I add final only in longer or more involved code where an argument might mistaken for a local or member variable.
#Another case added for the completeness
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}
record
Java 16 brings the new records feature. A record is a very brief way to define a class whose central purpose is to merely carry data, immutably and transparently.
You simply declare the class name along with the names and types of its member fields. The compiler implicitly provides the constructor, getters, equals & hashCode, and toString.
The fields are read-only, with no setters. So a record is one case where there is no need to mark the arguments final. They are already effectively final. Indeed, the compiler forbids using final when declaring the fields of a record.
public record Employee( String name , LocalDate whenHired ) // 🡄 Marking `final` here is *not* allowed.
{
}
If you provide an optional constructor, there you can mark final.
public record Employee(String name , LocalDate whenHired) // 🡄 Marking `final` here is *not* allowed.
{
public Employee ( final String name , final LocalDate whenHired ) // 🡄 Marking `final` here *is* allowed.
{
this.name = name;
whenHired = LocalDate.MIN; // 🡄 Compiler error, because of `final`.
this.whenHired = whenHired;
}
}
Sometimes it's nice to be explicit (for readability) that the variable doesn't change. Here's a simple example where using final can save some possible headaches:
public void setTest(String test) {
test = test;
}
If you forget the 'this' keyword on a setter, then the variable you want to set doesn't get set. However, if you used the final keyword on the parameter, then the bug would be caught at compile time.
Yes, excluding anonymous classes, readability and intent declaration it's almost worthless. Are those three things worthless though?
Personally I tend not to use final for local variables and parameters unless I'm using the variable in an anonymous inner class, but I can certainly see the point of those who want to make it clear that the parameter value itself won't change (even if the object it refers to changes its contents). For those who find that adds to readability, I think it's an entirely reasonable thing to do.
Your point would be more important if anyone were actually claiming that it did keep data constant in a way that it doesn't - but I can't remember seeing any such claims. Are you suggesting there's a significant body of developers suggesting that final has more effect than it really does?
EDIT: I should really have summed all of this up with a Monty Python reference; the question seems somewhat similar to asking "What have the Romans ever done for us?"
Let me explain a bit about the one case where you have to use final, which Jon already mentioned:
If you create an anonymous inner class in your method and use a local variable (such as a method parameter) inside that class, then the compiler forces you to make the parameter final:
public Iterator<Integer> createIntegerIterator(final int from, final int to)
{
return new Iterator<Integer>(){
int index = from;
public Integer next()
{
return index++;
}
public boolean hasNext()
{
return index <= to;
}
// remove method omitted
};
}
Here the from and to parameters need to be final so they can be used inside the anonymous class.
The reason for that requirement is this: Local variables live on the stack, therefore they exist only while the method is executed. However, the anonymous class instance is returned from the method, so it may live for much longer. You can't preserve the stack, because it is needed for subsequent method calls.
So what Java does instead is to put copies of those local variables as hidden instance variables into the anonymous class (you can see them if you examine the byte code). But if they were not final, one might expect the anonymous class and the method seeing changes the other one makes to the variable. In order to maintain the illusion that there is only one variable rather than two copies, it has to be final.
I use final all the time on parameters.
Does it add that much? Not really.
Would I turn it off? No.
The reason: I found 3 bugs where people had written sloppy code and failed to set a member variable in accessors. All bugs proved difficult to find.
I'd like to see this made the default in a future version of Java. The pass by value/reference thing trips up an awful lot of junior programmers.
One more thing.. my methods tend to have a low number of parameters so the extra text on a method declaration isn't an issue.
Using final in a method parameter has nothing to do with what happens to the argument on the caller side. It is only meant to mark it as not changing inside that method. As I try to adopt a more functional programming style, I kind of see the value in that.
Personally I don't use final on method parameters, because it adds too much clutter to parameter lists.
I prefer to enforce that method parameters are not changed through something like Checkstyle.
For local variables I use final whenever possible, I even let Eclipse do that automatically in my setup for personal projects.
I would certainly like something stronger like C/C++ const.
Since Java passes copies of arguments I feel the relevance of final is rather limited. I guess the habit comes from the C++ era where you could prohibit reference content from being changed by doing a const char const *. I feel this kind of stuff makes you believe the developer is inherently stupid as f*** and needs to be protected against truly every character he types. In all humbleness may I say, I write very few bugs even though I omit final (unless I don't want someone to override my methods and classes). Maybe I'm just an old-school dev.
Short answer: final helps a tiny bit but... use defensive programming on the client side instead.
Indeed, the problem with final is that it only enforces the reference is unchanged, gleefully allowing the referenced object members to be mutated, unbeknownst to the caller. Hence the best practice in this regard is defensive programming on the caller side, creating deeply immutable instances or deep copies of objects that are in danger of being mugged by unscrupulous APIs.
I never use final in a parameter list, it just adds clutter like previous respondents have said. Also in Eclipse you can set parameter assignment to generate an error so using final in a parameter list seems pretty redundant to me.
Interestingly when I enabled the Eclipse setting for parameter assignment generating an error on it caught this code (this is just how I remember the flow, not the actual code. ) :-
private String getString(String A, int i, String B, String C)
{
if (i > 0)
A += B;
if (i > 100)
A += C;
return A;
}
Playing devil's advocate, what exactly is wrong with doing this?
One additional reason to add final to parameter declarations is that it helps to identify variables that need to be renamed as part of a "Extract Method" refactoring. I have found that adding final to each parameter prior to starting a large method refactoring quickly tells me if there are any issues I need to address before continuing.
However, I generally remove them as superfluous at the end of the refactoring.
Follow up by Michel's post. I made myself another example to explain it. I hope it could help.
public static void main(String[] args){
MyParam myParam = thisIsWhy(new MyObj());
myParam.setArgNewName();
System.out.println(myParam.showObjName());
}
public static MyParam thisIsWhy(final MyObj obj){
MyParam myParam = new MyParam() {
#Override
public void setArgNewName() {
obj.name = "afterSet";
}
#Override
public String showObjName(){
return obj.name;
}
};
return myParam;
}
public static class MyObj{
String name = "beforeSet";
public MyObj() {
}
}
public abstract static class MyParam{
public abstract void setArgNewName();
public abstract String showObjName();
}
From the code above, in the method thisIsWhy(), we actually didn't assign the [argument MyObj obj] to a real reference in MyParam. In instead, we just use the [argument MyObj obj] in the method inside MyParam.
But after we finish the method thisIsWhy(), should the argument(object) MyObj still exist?
Seems like it should, because we can see in main we still call the method showObjName() and it needs to reach obj. MyParam will still use/reaches the method argument even the method already returned!
How Java really achieve this is to generate a copy also is a hidden reference of the argument MyObj obj inside the MyParam object ( but it's not a formal field in MyParam so that we can't see it )
As we call "showObjName", it will use that reference to get the corresponding value.
But if we didn't put the argument final, which leads a situation we can reassign a new memory(object) to the argument MyObj obj.
Technically there's no clash at all! If we are allowed to do that, below will be the situation:
We now have a hidden [MyObj obj] point to a [Memory A in heap] now live in MyParam object.
We also have another [MyObj obj] which is the argument point to a [Memory B in heap] now live in thisIsWhy method.
No clash, but "CONFUSING!!" Because they are all using the same "reference name" which is "obj".
To avoid this, set it as "final" to avoid programmer do the "mistake-prone" code.

Does a passed final variable in Java stay final on the other side?

I've just come across some code that's confusing me slightly; there are really 2 variations that I'd like to clarify.
Example 1:
public String getFilepath(){
final File file = new File(this.folder, this.filename);
return file.getAbsolutePath();
}
What would be the purpose of declaring file "final"? Since Java primitives are passed by value, and getAbsolutePath() is just returning a String, the variable won't be final on the other side (calling method), will it? And since the file variable only exists within the scope of these 2 lines, I can't really see any purpose of the final keyword. Is there something I'm missing? Anyone see a reason to do this?
Example 2:
public String getFilepath(){
final File file = new File(this.folder, this.filename);
return file;
}
Since here the actual object is being returned... Does that mean the file variable will be constant/final on the other side...? It doesn't seem to make sense.
In general, it seems to me that you pass a variable, without it's access type. As in, I can have a private variable in a function with a public get function that returns it - but the variable that receives it by calling the function has to specify an access modifier. So if it specifies public, the returned variable will be public in that scope. If it specifies private, the returned variable will be private in that scope. Is there a difference with final? Is the "constancy" of a variable something that can be passed? This strikes me as rather improbable, considering what I know of Java.
Or am I missing the point entirely and there's some other purpose of the final keyword in the above code?
Edit:
I checked back with the original developer who wrote the code, and he said he only put the final keyword in because he had originally thought the method would be a lot longer and wanted to ensure that the file stayed constant throughout. He also said that he generally declares variables that should not be changed as final, as a rule across the board and sort of on principle - a point that both the answers below mentioned. So it seems I was reading too much into a simple extra keyword included for standards reasons. Thanks everyone!
final in this case just means that the local reference file will be immutable. It has no meaning outside the method. Some coding conventions advocate having all variables final unless they need to be mutable so you'll see code like that when someone is following such guidelines.
Some people might tell you that there's a performance benefit to using final, but that is, in no way, conclusively proven.
The primary benefit of the final keyword is for the programmer to indicate that a class, method, or field should not be changed.
Bear in mind that declaring a variable final does not make the referenced object immutable. It just means that the variable cannot have its value reassigned. You can still run methods of the variable file that could change the File object internally.
In the two methods you give, I see no value in making the file variable final. Some code conventions advocate making all variable final unless the need to be modified. Some people don't subscribe to that. I consider it a variation on the precautionary principle.

Categories