What does "final" do if you place it before a variable?
Very basic question, but, what does "final" do if you place it before a variable such开发者_运维百科 as below...
final EditText myTextField = (EditText) findViewById(R.id.myTextField);
What does final
do?
Short Answer
Stops the "myTextField" variable being assigned to something else.
Long Answer
- Does NOT stop the "myTextField" variable being mutated, e.g. having its fields set to new values.
- Makes code more readable (IMHO) because the reader never has to wonder whether the "myTextField" variable will be reassigned later on in the code.
- Guards against the category of bug whereby variables are accidentally reassigned (same reasoning behind making instances immutable, only on a smaller scale).
For the reasons given above, I always apply the "final" modifier wherever I can to static fields, instance fields, local variables, and method parameters. It does bloat the code a little, but for me it's worth the extra readability and robustness.
The keyword final
, in this context, means that you cannot update the implicit pointer myTextField
to point to a different object (although you can modify the object pointed to by myTextField
). The keyword may also be used to prevent overriding (when applied to classes or methods).
One reason why you might see this is that anonymous classes that reference local variables can only reference variables marked final
. This is so that the anonymous classes need only store a duplicate reference and do not need to maintain the complete access to the local function stack. For example:
Runnable r = new Runnable() { public static void run() {
// do something with myTextField
// this would require myTextField to have been marked final.
}};
doSomethingLater(r);
One thing that none of the other answers have noted is that a final
attribute has special properties vis-a-vis the Java memory model. The net effect is that one thread can safely access a final
attribute's value without taking steps to synchronize with other threads.
FOLLOWUP
Is that JVM specific?
The specification of the Java memory model is part of the Java Language Specification, and (AFAIK) hasn't changed since Java 1.5. In that sense this is not JVM specific.
However, the behaviour of Java if you don't follow the rules (i.e. if your code does not properly synchronize its use of shared data) depends on all sorts of things, including the hardware you run the application on.
Among other things, the Java memory model is designed to allow multi-core machines to run many Java threads without having to continually flush the memory caches ... which would kill performance. Basically, it specifies some rules that will guarantee that one Java thread sees memory updates from another thread. If an application doesn't follow the rules, it is possible that a thread will see a stale (out of date) value for some field written by some other thread, resulting in occasional undefined behaviour.
The final
keyword will ensure that myTextField
holds the reference of whatever findViewByID() returns and disallows any other assignment to myTextField
variable i.e. after the execution of the
final EditText myTextField = (EditText) findViewById(R.id.myTextField);
If you try to assign any value to myTextField, you will get a compiler error.
You can't modify the reference of myTextField
once it is assigned. More information below from Wikipedia
A final variable can only be assigned once. This assignment does not grant the variable immutable status. If the variable is a field of a class, it must be assigned in the constructor of its class. (Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still mutable, if it was originally mutable.) Unlike the value of a constant, the value of a final variable is not necessarily known at compile time.
If a variable is marked as final then the value of that variable cannot be changed i.e final keyword when used with a variable makes it a constant. And if you try to change the value of that variable during the course of your program the compiler will give you an error.
The keyword final
declares myTextField
as a constant variable.
Trying to explain use of final
modifier with flow of code:
public static void main(String[] args) {
class Person {
String name;
}
Person peep1 = new Person(); // points to obj at address HEX001
peep1.name = "Mike";
System.out.println(peep1.name);
Person peep2 = new Person(); // points to obj at address HEX002
peep2.name = "Jenna";
System.out.println(peep2.name);
final Person peep3 = peep1; // also points to obj at address HEX001
System.out.println(peep3.name);
peep1.name = "pwnd"; // modifies obj at address HEX001
System.out.println(peep1.name);
System.out.println(peep3.name);
peep1 = peep2; // now it points to obj at address HEX002
System.out.println(peep1.name);
System.out.println(peep3.name); // still points to obj at address HEX001
peep2.name = "Henna"; // modifies obj at address HEX002
System.out.println(peep2.name);
peep3 = peep2; // compiler error "The final local variable peep3 cannot be assigned. It must be
// blank and not using a compound assignment"
System.out.println(peep3.name); // assuming it now points to obj at address HEX002
}
Output:
Mike
Jenna
Mike
pwnd
pwnd
Jenna
pwnd
Henna
精彩评论