referencing class variable to a local variable - java

why do some people make a new reference in method to a field variable?
public class Foo {
int mFoo[] = {1, 2, 3};
void method() {
int foo[] = mFoo; // WHY not just use mFoo?
print(foo[0]); // WHY not just use mFoo?
}
}

It can be a good idea if for example, at another place of your code, you change the value of mFoo. Especially in a multithreaded context, you would want to ensure you're still working on the right data.

It used to be the case (and still is with Java ME AFAIK) that loading a field into a local variable and using it multiple times was faster than access a field multiple times.
However, today using a local variable this way can confuse the JIT compiler and using a local variable this way can be slower.

It depends on your goal. If you want to modify whatever Object was passed in as a parameter you would not make a new instance of the type of the referenced Object.
Otherwise you would make a new instance which would you could modify freely without worrying about modifications to the passed in Object. This is commonly used in multi-threaded applications.

There's an accepted answer already, but the use makes more sense in this context:
private Class<?> clazz = ...;
public void foo() {
Class<?> current = clazz;
while (current != Object.class) {
// do some stuff.
current = current.superclass();
}
}
In this example you are constantly re-assigning "current" to a new value. Imagine the side effect without the variable, and if you kept doing:
clazz = clazz.superclass();
You'd be changing the field in the object itself, not locally to your method, so repeated calls to "foo" would not exhibit the behavior you are expecting.

It just doesn't make sense if you use just like this:
int[] local = somethingElse;
... // changes to local will reflect on somethingElse
It would make sense if a real copy would be done like:
int[] local = Arrays.copyOf(somethingElse,somethingElse.lenght())
... // changes to local will not reflect on somethingElse
The copy can prevent changing the elements that you will need on your method invoking other methods or by other Threads interference. In case that you have for example a method that changes this elements invoked at the same time you are using them. So, you can make a copy and work with them without being concern about the modification applied to it.
A test can be done with the following code:
int[] test = new int[] {1,2,3};
int[] test2 = Arrays.copyOf(test,test.length);
test2[0] = 9;
System.out.println(Arrays.toString(test));

In case of primitive types like int you're coping the values, not pointer, so your original array is still untouched after invoking method "print". It doesnt hold though for arrays

Related

Looking for a concise copy constructor implementation (java)

For 2 variables, the statements are okay to write in the copy constructor block. But for a situation, in which there are several variables, can please someone help me knowing how similar result can be attained? I trier using this but it turned out to be a final variable.
class Obj
{
int a, b;
Obj(int a, int b)
{this.a = a; this.b =b;}
Obj(Obj obj1)
//trying to copy every variable by concise logic here
//instead of writing for each and every variable
{a = obj1.a; b = obj1.b;}
}
class CopyObj2
{
public static void main(String[] args)
{
Obj obj1 = new Obj(5,10);
System.out.println("Obj1\t"+obj1.a+", "+obj1.b);
Obj obj2 = new Obj(obj1);
System.out.println("Obj2\t"+obj2.a+", "+obj2.b);
}
}
There is no native way to do that - the only way is to assign field values by hand, as you did.
As a helper - you can try to use Orika - Java bean mapping framework (works if your classes are beans).
I tried using this but it turned out to be a final variable.
this is the reference to your object. You can't assign another value to him - it just doesn't make a sense.
The copy constructor is used in java's AWT stemming Point, Rectangle, Polygon and other geometric classes. Typically where there are many objects.
One does not need a copy constructor for immutable classes with final fields.
Experience with mutable classes let me tend to advise switching to immutable classes.
With copy constructors one ends up with much copying or sharing internal data (like arrays or lists). The code style is not that nice.
For completeness:
There is also cloning Object.clone() as alternative to a copy constructor, but it is slowly falling out of favor, because of its overhead.
Then there is serialisation for copying too, which is still heavily in use, but should not be used here.

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.

Shared instance variable vs local variable

Is there a reason to prefer using shared instance variable in class vs. local variable and have methods return the instance to it? Or is either one a bad practice?
import package.AClass;
public class foo {
private AClass aVar = new AClass();
// ... Constructor
public AClass returnAClassSetted() {
doStuff(aVar);
return avar;
}
private void doStuff(AClass a) {
aVar = a.setSomething("");
}
}
vs.
import package.AClass;
public class foo {
// ... Constructor
public AClass returnAClassSetted() {
AClass aVar = new AClass();
aVar = doStuff();
return aVar;
}
private AClass doStuff() {
AClass aVar1 = new AClass();
aVar1.setSomething("");
return aVar1;
}
}
First one makes more sense to me in so many ways but I often see code that does the second. Thanks!
Instance variables are shared by all methods in the class. When one method changes the data, another method can be affected by it. It means that you can't understand any one method on its own since it is affected by the code in the other methods in the class. The order in which methods are called can affect the outcome. The methods may not be reentrant. That means that if the method is called, again, before it finishes its execution (say it calls a method that then calls it, or fires an event which then a listener calls the method) then it may fail or behave incorrectly since the data is shared. If that wasn't enough potential problems, when you have multithreading, the data could be changed while you are using it causing inconsistent and hard to reproduce bugs (race conditions).
Using local variables keeps the scope minimized to the smallest amount of code that needs it. This makes it easier to understand, and to debug. It avoids race conditions. It is easier to ensure the method is reentrant. It is a good practice to minimize the scope of data.
Your class name should have been Foo.
The two versions you have are not the same, and it should depend on your use case.
The first version returns the same AClass object when different callers call returnAClassSetted() method using the same Foo object. If one of them changes the state of the returned AClass object, all of them will get see the change. Your Foo class is effectively a Singleton.
The second version returns a new AClass object every time a caller calls returnAClassSetted() method using either the same or different Foo object. Your Foo class is effectively a Builder.
Also, if you want the second version, remove the AClass aVar = new AClass(); and just use AClass aVar = doStuff();. Because you are throwing away the first AClass object created by new AClass();
It's not a yes/no question. It basically depends on the situation and your needs. Declaring the variable in the smallest scope as possible is considered the best practice. However there may be some cases (like in this one) where, depending on the task, it's better to declare it inside/outside the methods. If you declare them outside it will be one instance, and it will be two on the other hand.
Instance properties represent the state of a specific instance of that Class. It might make more sense to think about a concrete example. If the class is Engine, one of the properties that might represent the state of the Engine might be
private boolean running;
... so given an instance of Engine, you could call engine.isRunning() to check the state.
If a given property is not part of the state (or composition) of your Class, then it might be best suited to be a local variable within a method, as implementation detail.
In Instance variables values given are default values means null so if it's an object reference, 0 if it's and int.
Local variables usually don't get default values, and therefore need to be explicitly initialized and the compiler generates an error if you fail to do so.
Further,
Local variables are only visible in the method or block in which they are declared whereas the instance variable can be seen by all methods in the class.

Accessing local variables in the main method via reflection

Just having a play around with Java reflection and I think I'm getting the hang of it for the most part. I understand from this question/answer that, for the most part, I'm limited to static variables. If I have an instance of the class though, I can access non-static variables, which does make sense, I get that much.
Say I have the following two classes:
public class A
{
private static int _staticInt;
public static void main(String[] args)
{
B instanceOfB = new B();
}
}
public class B
{
private int _nonStaticInt;
public Game() {}
}
I understand how to access _staticInt, that's not an issue.
My understanding is that I can get the Field for _nonStaticInt in the same way (i.e. Field f = B.class.getDeclaredField("_nonStaticInt");). From other research (javadocs, trails, etc) I have gathered that I need an instance of B in order to get the value of _nonStaticInt.
So my question; Since main is static, is it possible to access instanceOfB in order to access the value of _nonStaticInt? I don't think it is possible, but I thought it's always best to consult people that are more knowledgable than myself before giving up on the idea.
Since main is static, is it possible to access instanceOfB in order to access the value of _nonStaticInt?
"No." Local variables (being in a static method or not) cannot be accessed with the Java Reflection API. Reflection only works at the type level, not the byte-code level2.
The stated understanding of the linked question is correct; reflection access of a non-static (instance) field logically requires an instance. That is, the issue then isn't about reflecting on the B type, the issue is about obtaining the B instance (which is assigned to a local variable) to reflect upon.
To do this the B instance has to be "bled" somehow - e.g. assigned to a static field or passed as an argument to a method/constructor from main1 - so that it can be used with reflection later as the object who's instance members are to be accessed.
The cleanest approach would probably be to pass the B instance down through the appropriate context (or "DI"), perhaps with the aide of IoC .. and maybe changing the type to avoid the use of reflection entirely.
1 Another possible way to "bleed" the B instance is to attach a debugger and inspect/use the local variable within the main methods executing frame - but this sounds like trying to swat a fly with a club.
2 Even tooling like BCEL/ASM wouldn't immediately help during the execution of the main method. Rather it would be used to deconstruct the method, add in the required hooks/code to "bleed" or use the instance created, and then construct a modified method to execute.
Yes, you can get the value of _nonStaticInt in that same way:
B instanceOfB = new B();
Field f = B.class.getDeclaredField("_nonStaticInt");
// Because the variable is private you need this:
f.setAccessible(true);
Object content = f.get(instanceOfB);
System.out.println(content);
The value will be 0, that is the default value for an int.

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.

Categories