Eclipse will give an error, "The left-hand side of an assignment must be a variable", when I try something like:
public class Thing{
String a1;
int a2;
public void meth(){
Thing A = new Thing();
this = A;
}
}
I had to assign each variable (this.a1 = A.a1; this.a2 = A.a2;) as a work around.
Are there other ways to do this without going through each variable field?
And if this is not a variable what is it called?
this is a pseudo-variable that points to the current instance of the object, it can not be reassigned. It's also considered a keyword in the language, according to section §3.9 of the Java Language Specification.
No, there is no easy shortcut.
And if "this" is not a variable what is it called?
this is not a variable, it's a keyword.
Even though this is special, in many respects it acts like a reference. Therefore, for consistency, this = A would have to be a reference assignment, which doesn't quite make sense.
You seem to be expecting this = A to perform a field-by-field copy from A to this, and indeed Java's designers could choose do that in this case. However, this would be inconsistent with other reference assignments, and the overall benefits of having this as an exception are not at all clear.
this refers to this instance of the class.
You cannot assign to this
this is a java reserved keyword which refers to the current object. its not a variable its a java reserved keyword.
so this = A; is invalid. using this keyword we can refer to any instance variable or method of the current object. you have to refer to the instance variable like:
this.a1 = A.a1;
From Doc:
The most common reason for using the this keyword is because a field
is shadowed by a method or constructor parameter.
You can't assign to this in Java. It's not a variable; it's a keyword.
One thing you might consider, if you don't need a particular instance, is just returning your new instance.
public class Thing{
String a1;
int a2;
public Thing meth(){
Thing A = new Thing();
return A;
}
}
and you'd use it like
whatever = whatever.meth();
According to java lang spec §15.8.3 this is a keyword that is either an expression or statement
When used as a primary expression this denotes a value that is a reference to the object for which the instance method was invoked.
Expression: Something which evaluates to a value. Example: x++
The keyword this is also used in a special explicit constructor invocation statement
Statement: Syntactic elements that control the execution of a program, which are executed for their effect and do not have values Example: if (true)
In either case it is not a variable
Variable: A storage location with an associated type
In your case this is an expression and not a variable. But for all intents an purposes just call it a keyword
Keyword: A character sequence, formed from ASCII letters, are reserved for use ... that cannot be used as a variable name
this refers to the owner of the method.
In this case, the owner is the object itself.
Sometime, this may not refer to the class that you are writing code. Such as in the annoymous class. A common example is the anonymous listener.
button.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
this; // refers to the ActionListener
}
}
);
In addition, you can return this can do method chaining. Supposed you have a class called Homework and it has a method addTask.
public Homework addTask(String task){
return this;
}
you can call the addTask method like
homework.addTask("a").addTask("b").addTask("c");
I think the OP is asking for the ability to assign the contents of one object to another, rather than to assign a new value to the "this" pointer. C++ has this ability -- you can override the assignment operator -- but Java has no such ability.
It would be a nice feature to have in some occasional cases, but it's simply not currently possible, and it doesn't really fit the Java "mold" to provide the function in the future.
The capability would be more useful (and there would be more motivation to provide it) if Java allowed objects to be embedded in other objects (vs simply embedding referenced), but that's not in the cards either.
There is no1 way to copy the values of all fields from one instance onto another in the basic Java language. And you should typically not need it. You can most often just replace the reference to the new instance or work directly on the target instance.
In your case when you want to reset all fields of a object to the initial values (and there is seldomly a need for it) you typically use a reset method which eighter works on its own instance or is a static one working on any given object.
So
class A {
String a1; int a2;
void reset() { a1 = ""; a2 = 0; }
}
would be used as
A a = new A();
// modify a
a.reset();
and
class A {
String a1; int a2;
static void reset(A anotherA) { anotherA.a1 = ""; anotherA.a2 = 0; }
}
and use it like:
A.reset(a);
In both cases it makes sense to use the reset method also for setting the initial values in the constructor: A() { A.reset(this); } or A() { this.reset(); }
1 actually there are some libraries to do it, and you can code it with the help of reflection, the only reason I see it is used is to implement a clone() method or for some kind of wrapping/stubbing.
It sounds to me like what you're trying to do is have a method that reinitializes your object, i.e., set's it back to it's initial values. That's why you want to create a new object, and assign it to the current object, right?
If that's the case, let's try a different way of doing it, since, as has been said, you can't reassign this.
What if, instead of doing that, you tried something like this:
public class Thing {
String a1;
int a2;
public Thing() {
this.meth();
}
public void meth() {
this.a1 = "a1";
this.a2 = 2;
}
}
This way, Thing.meth() actually initializes your object, and the constructor calls it when the object is created. Then you can call it again whenever you'd like.
==Disclaimer, I don't know java==
You would want to assign manually.
I'm not sure why you are trying to create a new instance of Thing inside Thing, but as you don't set the values of a1 and a2 you would need to assign them the way you did.
this is a reserved keyword pointing the class object it is inside.
For example, if you wanted to have another function named fish() your code may look something like this.
public class Thing{
String a1;
int a2;
public Thing meth(){
Thing A = new Thing();
return A;
}
public Thing fish(){
this.a1 = "foo";
this.meth();
return A;
}
}
When you do this = stuff; you are trying to replace the current object instance reference (in this case, the one that you are initializing in the constructor) with another thing, and (in the particular case of java) thats illegal and the language forbids you of doing it.
Think about it, if you could replace the reference to your current instance just like that, then you could incur in some serious memory and security problems (the reference to the constructed object will be lost and overrided by some unknown object).
What is totally valid is referencing members of your current object using the . operator, because they are owned by this, so no problems should arise (at least not evident ones).
The JVM has some inner security measures (e.g., method max stack size verification, class file format validation, etc) that prevents from easy binary manipulation and are enforced by the language syntax. This could be seen as one of those.
Related
Consider we have classes like this:
class A {
public B b;
public void someFunc() { // called sometime
b = new B();
}
}
Class B's constructor assigns some inner variables.
Field b is not thread-safe in the sense another thread can view b not-null when B constructor hasn't finished. (during someFunc execution)
My question is the following: how can it be (from the logic perspective) that the constructor hasn't finished yet?
For me reordering of such kind is magic.
In the context of thread safety, this usually happens because of just-in-time (JIT) compilers. A JIT compiler takes Java byte code and translates it in to machine code to make it run faster. During translation, it's able to make a lot of optimizations, such as inlining various methods and constructors.
Supposing B had a constructor like this:
class B {
int x;
B(int x) { this.x = x; }
}
When a constructor is inlined, it takes Java code that's something like this:
b = new B(1);
And translates it to machine code that takes steps similar to the following:
Allocate space for a B object somehow.
Store the pointer to that memory in to b.
Store 1 in b.x.
In other words, code which is analogous to this (in terms of ordering):
b = new B();
b.x = 1;
But we don't actually call a constructor at all. We'd just allocate a B, however the JVM does it internally, and assign b.x directly. Calling the constructor would involve jump instructions, so it's a bit faster to inline it.
There's an example like that in the famous "Double-Checked Locking is Broken" Declaration.
A regular Java compiler would be allowed to inline constructors too, but regular Java compilers don't typically perform many optimizations.
Instance of object can "escape" from constructor, like that:
public class EscapeDemo {
static void escape(B b) {
System.out.println(b.strA);
System.out.println(b.strB); // still null in this example, even if field is final and initialized to non-null value.
}
public static void main(String[] args) {
System.out.println(new B());
}
}
class B {
final String strA;
final String strB;
B() {
strA = "some operations";
EscapeDemo.escape(this);
strB = "here";
}
}
prints:
some operations
null
B#hashcode
And in similar way that reference could escape to some code that will use it from other thread.
Like Andy Guibert added in comment: this is a bad practice to write such code - as it might be source of many weird errors and hard to trace bug - like here we have something that should not be a null, but it is a null.
And if you want to do something with object instance on creation it is much better idea to create static factory method that will create instance and then do something with (like add to some collection/registry) it and then return it.
Also if you include usage of weird code nad hacks - in bytecode java object creation is separated from constructor call, so it is possible from bytecode level to create an object, pass it somewhere and call constructor in some other place.
But otherwise field is assigned after right side expression is executed so for code
b = new B();
field b can be only null or B instance after constructor is called. Unless you would set that field from inside of B constructor like in my escape example.
If I understand your question correctly. You are asking about if you create an instance of Object A which has a field b of type B and the field b is not initialized when A is created but only some other object calls someFunc(). What will happen when some other thread tries to access this field b?
If so, when you create a new object of type B the JVM will allocate some memory for this object and then will return a reference which will be held in the field b. If other thread tries to access the field b before it got the reference of the new object, it will return null otherwise will return the reference to the newly created object.
So I have a simple programming question that I can't seem to find the answer for. While browsing some code from Google I noticed that they put 'this' in front of a lot of methods in their code. What is the purpose of doing this? Does it have any benefits over not using it?
An example:
this.doMethod();
Compared to:
doMethod();
I'm sure its a simple answer, I just like being able to understand all of the code that I read.
No, it makes no difference at all for method calls. Use whichever you find more readable.
Note that it does make a difference when disambiguating between instance variables and parameters (or other local variables though). For example:
public void setFoo(int foo) {
this.foo = foo;
}
That's assigning the instance variable a value from the parameter - just using foo = foo; would be a no-op.
this represents the object instance of the current class. In programming practice, most of the time, it is used to break the ambiguity. e.g. in example, there is a class variable named name and method parameter named named, so this is used to differentiate the two.
public void setName(String name){
this.name= name;
}
If you don't have any ambiguity then it doesn't create much difference i.e. setName("John"); and this.setName("John"); is same thing. But still there is one difference. this.setName("John"); follows the same pattern as you are calling the method on objects(e.g. emp.setName("A");); here this representing the sane class object.
There is no difference between them at all. You always call a method on some reference. If you don't use any reference, this reference is implicit.
So, doMethod() is same as this.doMethod(). By using this, you just make it explicit.
One place where it is required to use this reference explicitly is the place where you are assigning the value of method/constructor parameter to the instance variable, and both have same name, as in the below example:
public Demo(int var) { // Constructor
this.var = var;
}
So, in the above example, this.var refers to instance variable and is different from var, which refers to constructor parameter.
if java is always pass variables by reference, why does eclipse generate the bean with out any consideration.
instead of:
return myStr;
needs to be
return new String(myStr);
no?
Edit
Ok, my example was bad.
lets leave eclipse, When I want to return a Custom object. Do i need to create a "copy constructor" and return it, like that:
return new MyCustomObject(myCustomObject);
class MyCustomObject{
private String str;
public MyCustomObject(String str){
this.str = str;
}
public MyCustomObject(MyCustomObject obj){
this.str = obj.str;
}
}
Must I write that?
No.
In Java, every object variable is a reference. Objects cannot be passed by value, only primitives can (and always are). Well, that's slightly misleading. The reference is passed by value, but you can think of everything being a reference, just not in a C++ sense.
Perhaps it's easiest to use an example.
SomeObject foo;
public void doSomething(SomeObject bar) {
bar.whatever();
bar = new SomeObject();
bar.someOtherMethod();
}
public void doStuff() {
foo = new SomeObject();
doSomething(foo);
}
So, foo is a reference to an instance of SomeObject. When doSomething is called, the value of that reference is copied to bar, so now foo and bar are references to the same SomeObject.
The line bar.whatever() calls whatever on the same object that foo refers to.
bar = new SomeObject() means that foo and bar now refer to different SomeObject instances, so someOtherMethod is not called on the object that foo refers to.
This is completely different to C++, where
void doSomething(SomeObject& bar) {
bar = whatever;
}
has a totally different meaning. You really should not ever think of Java in C++ terms.
Regarding your example, Strings are immutable in Java so it wouldn't matter even if objects could be passed by value.
Regarding your second example, if you want to return an object that the caller cannot use to pollute your internal state then, yes, you need to have a copy constructor (or something equivalent).
For example:
class ClassWithInternalList {
private List<String> reallyImportantData;
public List<String> getImmutableViewOfData() {
// Take advantage of the java.util.Collections tool for making a List immutable.
return Collections.unmodifiableList(reallyImportantData);
}
public List<String> getSafeCopyOfData() {
// Return a copy that the caller can modify without changing reallyImportantData.
return new ArrayList<String>(reallyImportantData);
}
public List<String> justGetTheData() {
// Return a reference to reallyImportantData that the caller can modify at will.
return reallyImportantData;
}
}
You can choose the appropriate type of return value (normal reference, immutable view or copy) depending on the situation. Any or all of the three options could be appropriate depending on exactly what you are doing.
java.util.Collections makes it easy to get an immutable view of a Collection, but for custom classes you'll need to do your own immutable-ness.
Remember that you only need to do this if there is an issue with mutability. Your MyCustomObject example is still immutable (since the caller cannot change any state in the returned MyCustomObject instance), so the question is still kinda moot.
If the variable is primitive or immutable,you modify what returned won't influence the original property.
Other condition, the variable is a custom type,maybe your class defines a constructor with itself like String,maybe not . So eclipse does not know how to generate it's copy.
As all knows,java pass reference,so java programmers are used to return the reference and allow other modify.Eclipse implement it as default.
If you don't like it ,you can return a copy or implements Immutable.
You usually do not want to create a new object when using getter. What you usually want is to get the reference to object's attribute to work with it easier, for encapsulation and to have the right value even when something else changes the value of the attribute before you use it.
Creating a new instance of an object by method which is called often, is not expected to do it and even does not declare doing such thing is freaking anti-pattern.
This question already has answers here:
Why should I use the keyword "final" on a method parameter in Java?
(12 answers)
Closed 7 years ago.
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
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. This is because objects in Java really are pointers to objects. And only the pointer is copied (and will be final in your method), not the actual object.
There is a circumstance where you're required to declare it final —otherwise it will result in compile error—, namely passing them through into an anonymous class or a lambda. Here's a basic example using an anonymous class:
public FileFilter createFileExtensionFilter(final String extension) {
FileFilter fileFilter = new FileFilter() {
public boolean accept(File file) {
return file.getName().endsWith(extension);
}
};
// Imagine what would happen when we're allowed to change extension here?
// extension = "foo";
return fileFilter;
}
And here's the exact same example in lambda flavor:
public FileFilter createFileExtensionFilter(final String extension) {
FileFilter fileFilter = file -> file.getName().endsWith(extension);
// Imagine what would happen when we're allowed to change extension here?
// extension = "foo";
return fileFilter;
}
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 after creation of the anonymous class or lambda would namely cause the instance of the anonymous class or lambda to behave different after the moment of creation.
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.
The final keyword on a method parameter means absolutely nothing to the caller. It also means absolutely nothing to the running program, since its presence or absence doesn't change the bytecode. It only ensures that the compiler will complain if the parameter variable is reassigned within the method. That's all. But that's enough.
Some programmers (like me) think that's a very good thing and use final on almost every parameter. It makes it easier to understand a long or complex method (though one could argue that long and complex methods should be refactored.) It also shines a spotlight on method parameters that aren't marked with final.
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...
final means you can't change the value of that variable once it was assigned.
Meanwhile, the use of final for the arguments in those methods means it won't allow the programmer to change their value during the execution of the method.
This only means that inside the method the final variables can not be reassigned.
final keyword in the method input parameter is not needed. Java creates a copy of the reference to the object, so putting final on it doesn't make the object final but just the reference, which doesn't make sense
If you declare any parameter as final, you cannot change the value of it.
class Bike11 {
int cube(final int n) {
n=n+2;//can't be changed as n is final
n*n*n;
}
public static void main(String args[]) {
Bike11 b=new Bike11();
b.cube(5);
}
}
Output: Compile Time Error
For more details, please visit my blog: http://javabyroopam.blogspot.com
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.
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.