How does the "final" keyword in Java work? (I can still modify an object.)
Asked Answered
T

20

569

In Java we use final keyword with variables to specify its values are not to be changed. But I see that you can change the value in the constructor / methods of the class. Again, if the variable is static then it is a compilation error.

Here is the code:

import java.util.ArrayList;
import java.util.List;

class Test {
  private final List foo;

  public Test()
  {
      foo = new ArrayList();
      foo.add("foo"); // Modification-1
  }
  public static void main(String[] args) 
  {
      Test t = new Test();
      t.foo.add("bar"); // Modification-2
      System.out.println("print - " + t.foo);
  }
}

Above code works fine and no errors.

Now change the variable as static:

private static final List foo;

Now it is a compilation error. How does this final really work?

Tufa answered 27/3, 2013 at 9:2 Comment(5)
since foo is not visible - how could it compile?Visitor
@therealprashant that isn't true. Private static variables are valid, they are accessible from static methods inside the class they are defined in. A static variable means that the variable exists once and isn't bound to an instance of a class.Placement
@Placement Oh Yes ! thankyou. But still I won't delete the comment to help people who are thinking like me and then your comment will make them think in correct direction.Wainscoting
@Wainscoting okay no worries!Placement
Related post - What is the equivalent of Java's final in C#?Arbe
J
608

You are always allowed to initialize a final variable. The compiler makes sure that you can do it only once.

Note that calling methods on an object stored in a final variable has nothing to do with the semantics of final. In other words: final is only about the reference itself, and not about the contents of the referenced object.

Java has no concept of object immutability; this is achieved by carefully designing the object, and is a far-from-trivial endeavor.

Jat answered 27/3, 2013 at 9:3 Comment(14)
But in my example, i modify it in constructor as well as in main methodTufa
Please read my updated answer. It should contain enough additional detail to fully answer your doubts.Jat
try to do t.foo = new ArrayList(); in the main method and you will get compilation error...the reference foo is binded to just one final object of ArrayList...it cannot point to any other ArrayListPraxis
I have a question. Someone I know claimed "final" also makes the variable be stored on the stack. Is this correct? I've searched everywhere and couldn't find any reference that can approve or disapprove this claim. I've searched on both Java and Android documentation . Also searched for "Java memory model". Maybe it works this way on C/C++, but I don't think it works this way on Java. Am I correct?Necrolatry
@androiddeveloper Nothing in Java can explicitly control stack/heap placement. More specifically, stack placement as decided by the HotSpot JIT compiler is subject to escape analysis, which is far more involved than checking whether a variable is final. Mutable objects can be stack-allocated as well. final fields may help the escape analysis, though, but that's a quite indirect route. Also note that effectively final variables have identical treatement as those marked final in the source code.Jat
@androiddeveloper he may have been talking about some semantic that the Dalvik VM is known to use (since that's the VM your code is likely running on in Android). But Marko is correct, there's no implementation guarantee here.Suit
@MarkoTopolnik I knew it. I kept telling him this is incorrect and doesn't make sense. Thank you. I have one question though: does the runtime do anything with the "final" keyword? Does the "final" keyword even get to be into the files that are used by the VM ? Or is it just for the developer/s, to make them know this variable isn't supposed to change its value? According to what you've written, I assume it depends on the compiler and the VM to decide what to do with it.Necrolatry
final is present in the class file and has significant semantic consequences for an optimizing runtime. It may also incur costs because the JLS has a strong guarantee about the consistency of final fields of an object. For example, the ARM processor must use an explicit memory barrier instruction on the end of each constructor of a class which has final fields. On other processors this is not needed, however.Jat
"Java has no concept of object immutability" - how am I then not able to change the contents of a String once it has been initialized ? What am I missing ?Dugaid
@miguel Because String has no methods that change its state. Immutability is not a language feature, the Java compiler has no idea which object is immutable and which isn't.Jat
I see the point you were making now. Can compilers enforce immutability even if object is mutable (I know both these things sounds contradictory to each other) but I am trying to understand how can this be enforced on compiler level.Dugaid
@Miguel One attempt was the C++ const, but it mostly failed.Jat
@MarkoTopolnik how? It is one of the most useful features of C++.Ferine
@DariusDuesentrieb From my info, its problem is that it basically splits the APIs into the const and non-const worlds and creates friction between them.Jat
U
649

This is a favorite interview question. With this questions, the interviewer tries to find out how well you understand the behavior of objects with respect to constructors, methods, class variables (static variables) and instance variables.
Now a days interviewers are asking another favorite question what is effectively final from java 1.8.
I will explain in the end about this effectively final in java 1.8.

import java.util.ArrayList;
import java.util.List;

class Test {
    private final List foo;

    public Test() {
        foo = new ArrayList();
        foo.add("foo"); // Modification-1
    }

    public void setFoo(List foo) {
       //this.foo = foo; Results in compile time error.
    }
}

In the above case, we have defined a constructor for 'Test' and gave it a 'setFoo' method.

About constructor: Constructor can be invoked only one time per object creation by using the new keyword. You cannot invoke constructor multiple times, because constructor are not designed to do so.

About method: A method can be invoked as many times as you want (Even never) and the compiler knows it.

Scenario 1

private final List foo;  // 1

foo is an instance variable. When we create Test class object then the instance variable foo, will be copied inside the object of Test class. If we assign foo inside the constructor, then the compiler knows that the constructor will be invoked only once, so there is no problem assigning it inside the constructor.

If we assign foo inside a method, the compiler knows that a method can be called multiple times, which means the value will have to be changed multiple times, which is not allowed for a final variable. So the compiler decides constructor is good choice! You can assign a value to a final variable only one time.

Scenario 2

private static final List foo = new ArrayList();

foo is now a static variable. When we create an instance of Test class, foo will not be copied to the object because foo is static. Now foo is not an independent property of each object. This is a property of Test class. But foo can be seen by multiple objects and if every object which is created by using the new keyword which will ultimately invoke the Test constructor which changes the value at the time of multiple object creation (Remember static foo is not copied in every object, but is shared between multiple objects.)

Scenario 3

t.foo.add("bar"); // Modification-2

Above Modification-2 is from your question. In the above case, you are not changing the first referenced object, but you are adding content inside foo which is allowed. Compiler complains if you try to assign a new ArrayList() to the foo reference variable.
Rule If you have initialized a final variable, then you cannot change it to refer to a different object. (In this case ArrayList)

final classes cannot be subclassed
final methods cannot be overridden. (This method is in superclass)
final methods can override. (Read this in grammatical way. This method is in a subclass)

Now let's see what is effectively final in java 1.8?

public class EffectivelyFinalDemo { //compile code with java 1.8
    public void process() {
        int thisValueIsFinalWithoutFinalKeyword = 10; //variable is effectively final
        
        //to work without final keyword you should not reassign value to above variable like given below 
        thisValueIsFinalWithoutFinalKeyword = getNewValue(); // delete this line when I tell you.
        
        class MethodLocalClass {
            public void innerMethod() {
                //below line is now showing compiler error like give below
                //Local variable thisValueIsFinalWithoutFinalKeyword defined in an enclosing scope must be final or effectively final
                System.out.println(thisValueIsFinalWithoutFinalKeyword); //on this line only final variables are allowed because this is method local class
                // if you want to test effectively final is working without final keyword then delete line which I told you to delete in above program.  
            }
        }
    }

    private int getNewValue() {
        return 0;
    }
}

Above program will throw error in java 1.7 or <1.8 if you do not use final keyword. Effectively final is a part of Method Local Inner classes. I know you would rarely use such effectively final in method local classes, but for interview we have to be prepared.

Up answered 27/3, 2013 at 10:8 Comment(6)
Just to be clear. In Scenario 2 are you saying that foo would be set multiple times despite the final designation if foo is set in the Test class and multiple instances of Test are created?Joseph
Didn't understood last line for scenario 2: But foo can be .. multiple objects.) Is that mean, if I create multiple object at a time, then which object is initializing final variable is depends on execution?Consentaneous
I think a helpful way to think about scenario 3 is you are assigning final to the memory address referenced by foo which is an ArrayList. You are not assigning final to the memory address referenced by the first element of foo (or any element for that matter). Therefore you can't change foo but you can change foo[0].Hyderabad
@Joseph As it stands, Scenario 2 would cause a compile-time error because of foo = new ArrayList(); - foo refers to the static variable because we're inside the same class.Durra
I'm a C++ developer learning Java. Is it safe to think of final on a variable as the same as the const keyword in C++?Hysterical
About scenatio 2. I suppose that compilation error because static final variable is not initialized in class scope. And it'is not related to multiple instantiating using constructor. As you know you can use static variable even without instantiating Test class. Then if you initialize that you will have error because you can' not reassign again final variable to another foo object using constructor.Defamation
J
608

You are always allowed to initialize a final variable. The compiler makes sure that you can do it only once.

Note that calling methods on an object stored in a final variable has nothing to do with the semantics of final. In other words: final is only about the reference itself, and not about the contents of the referenced object.

Java has no concept of object immutability; this is achieved by carefully designing the object, and is a far-from-trivial endeavor.

Jat answered 27/3, 2013 at 9:3 Comment(14)
But in my example, i modify it in constructor as well as in main methodTufa
Please read my updated answer. It should contain enough additional detail to fully answer your doubts.Jat
try to do t.foo = new ArrayList(); in the main method and you will get compilation error...the reference foo is binded to just one final object of ArrayList...it cannot point to any other ArrayListPraxis
I have a question. Someone I know claimed "final" also makes the variable be stored on the stack. Is this correct? I've searched everywhere and couldn't find any reference that can approve or disapprove this claim. I've searched on both Java and Android documentation . Also searched for "Java memory model". Maybe it works this way on C/C++, but I don't think it works this way on Java. Am I correct?Necrolatry
@androiddeveloper Nothing in Java can explicitly control stack/heap placement. More specifically, stack placement as decided by the HotSpot JIT compiler is subject to escape analysis, which is far more involved than checking whether a variable is final. Mutable objects can be stack-allocated as well. final fields may help the escape analysis, though, but that's a quite indirect route. Also note that effectively final variables have identical treatement as those marked final in the source code.Jat
@androiddeveloper he may have been talking about some semantic that the Dalvik VM is known to use (since that's the VM your code is likely running on in Android). But Marko is correct, there's no implementation guarantee here.Suit
@MarkoTopolnik I knew it. I kept telling him this is incorrect and doesn't make sense. Thank you. I have one question though: does the runtime do anything with the "final" keyword? Does the "final" keyword even get to be into the files that are used by the VM ? Or is it just for the developer/s, to make them know this variable isn't supposed to change its value? According to what you've written, I assume it depends on the compiler and the VM to decide what to do with it.Necrolatry
final is present in the class file and has significant semantic consequences for an optimizing runtime. It may also incur costs because the JLS has a strong guarantee about the consistency of final fields of an object. For example, the ARM processor must use an explicit memory barrier instruction on the end of each constructor of a class which has final fields. On other processors this is not needed, however.Jat
"Java has no concept of object immutability" - how am I then not able to change the contents of a String once it has been initialized ? What am I missing ?Dugaid
@miguel Because String has no methods that change its state. Immutability is not a language feature, the Java compiler has no idea which object is immutable and which isn't.Jat
I see the point you were making now. Can compilers enforce immutability even if object is mutable (I know both these things sounds contradictory to each other) but I am trying to understand how can this be enforced on compiler level.Dugaid
@Miguel One attempt was the C++ const, but it mostly failed.Jat
@MarkoTopolnik how? It is one of the most useful features of C++.Ferine
@DariusDuesentrieb From my info, its problem is that it basically splits the APIs into the const and non-const worlds and creates friction between them.Jat
O
247

Final keyword has a numerous way to use:

  • A final class cannot be subclassed.
  • A final method cannot be overridden by subclasses
  • A final variable can only be initialized once

Other usage:

  • When an anonymous inner class is defined within the body of a method, all variables declared final in the scope of that method are accessible from within the inner class

A static class variable will exist from the start of the JVM, and should be initialized in the class. The error message won't appear if you do this.

Overby answered 27/3, 2013 at 9:9 Comment(4)
This is by far my favorite answer. Simple and straight-forward, this is what I would expect to read in online docs about java.Watterson
So in static variables we can initialize as many times as we want?Canvass
@jorgesaraiva yes, static variables are not constants.Overby
@jorgesaraiva You can assign (not initialize) static fields (as long as they are not final) as many times as you want. See this wiki for the difference between assignment and initialization.Arlindaarline
J
73

The final keyword can be interpreted in two different ways depending on what it's used on:

Value types: For ints, doubles etc, it will ensure that the value cannot change,

Reference types: For references to objects, final ensures that the reference will never change, meaning that it will always refer to the same object. It makes no guarantees whatsoever about the values inside the object being referred to staying the same.

As such, final List<Whatever> foo; ensures that foo always refers to the same list, but the contents of said list may change over time.

Judd answered 27/3, 2013 at 9:12 Comment(1)
Finally, the answer I was searching for.Ferine
N
24

If you make foo static, you must initialize it in the class constructor (or inline where you define it) like the following examples.

Class constructor (not instance):

private static final List foo;

static
{
   foo = new ArrayList();
}

Inline:

private static final List foo = new ArrayList();

The problem here is not how the final modifier works, but rather how the static modifier works.

The final modifier enforces an initialization of your reference by the time the call to your constructor completes (i.e. you must initialize it in the constructor).

When you initialize an attribute in-line, it gets initialized before the code you have defined for the constructor is run, so you get the following outcomes:

  • if foo is static, foo = new ArrayList() will be executed before the static{} constructor you have defined for your class is executed
  • if foo is not static, foo = new ArrayList() will be executed before your constructor is run

When you do not initilize an attribute in-line, the final modifier enforces that you initialize it and that you must do so in the constructor. If you also have a static modifier, the constructor you will have to initialize the attribute in is the class' initialization block : static{}.

The error you get in your code is from the fact that static{} is run when the class is loaded, before the time you instantiate an object of that class. Thus, you will have not initialized foo when the class is created.

Think of the static{} block as a constructor for an object of type Class. This is where you must do the initialization of your static final class attributes (if not done inline).

Side note:

The final modifier assures const-ness only for primitive types and references.

When you declare a final object, what you get is a final reference to that object, but the object itself is not constant.

What you are really achieving when declaring a final attribute is that, once you declare an object for your specific purpose (like the final List that you have declared), that and only that object will be used for that purpose: you will not be able to change List foo to another List, but you can still alter your List by adding/removing items (the List you are using will be the same, only with its contents altered).

Neolithic answered 27/3, 2013 at 9:6 Comment(0)
H
13

The final keyword in java is used to restrict the user. The java final keyword can be used in many context. Final can be:

  1. variable
  2. method
  3. class

The final keyword can be applied with the variables, a final variable that has no value, is called blank final variable or uninitialized final variable. It can be initialized in the constructor only. The blank final variable can be static also which will be initialized in the static block only.

Java final variable:

If you make any variable as final, you cannot change the value of final variable(It will be constant).

Example of final variable

There is a final variable speedlimit, we are going to change the value of this variable, but It can't be changed because final variable once assigned a value can never be changed.

class Bike9{  
    final int speedlimit=90;//final variable  
    void run(){  
        speedlimit=400;  // this will make error
    }  

    public static void main(String args[]){  
    Bike9 obj=new  Bike9();  
    obj.run();  
    }  
}//end of class  

Java final class:

If you make any class as final, you cannot extend it.

Example of final class

final class Bike{}  

class Honda1 extends Bike{    //cannot inherit from final Bike,this will make error
  void run(){
      System.out.println("running safely with 100kmph");
   }  

  public static void main(String args[]){  
      Honda1 honda= new Honda();  
      honda.run();  
      }  
  }  

Java final method:

If you make any method as final, you cannot override it.

Example of final method (run() in Honda cannot override run() in Bike)

class Bike{  
  final void run(){System.out.println("running");}  
}  

class Honda extends Bike{  
   void run(){System.out.println("running safely with 100kmph");}  

   public static void main(String args[]){  
   Honda honda= new Honda();  
   honda.run();  
   }  
}  

shared from: http://www.javatpoint.com/final-keyword

Hilton answered 3/1, 2017 at 4:45 Comment(0)
A
12

This is a very good interview question. Sometimes they might even ask you what is the difference between a final object and immutable object.

1) When someone mentions a final object, it means that the reference cannot be changed, but its state(instance variables) can be changed.

2) An immutable object is one whose state can not be changed, but its reference can be changed. Ex:

    String x = new String("abc"); 
    x = "BCG";

ref variable x can be changed to point a different string, but value of "abc" cannot be changed.

3) Instance variables(non static fields) are initialized when a constructor is called. So you can initialize values to you variables inside a constructor.

4) "But i see that you can change the value in the constructor/methods of the class". -- You cannot change it inside a method.

5) A static variable is initialized during class loading. So you cannot initialize inside a constructor, it has to be done even before it. So you need to assign values to a static variable during declaration itself.

Alyose answered 24/9, 2014 at 20:34 Comment(0)
S
11

Worth to mention some straightforward definitions:

Classes/Methods

You can declare some or all of a class methods as final, in order to indicate that the method cannot be overridden by subclasses.

Variables

Once a final variable has been initialized, it always contains the same value.

final basically avoid overwrite/superscribe by anything (subclasses, variable "reassign"), depending on the case.

Scrutator answered 29/6, 2016 at 16:5 Comment(2)
I think final definition about variables is a bit short; "In Java, when final keyword is used with a variable of primitive data types (int, float, .. etc), value of the variable cannot be changed but When final is used with non-primitive variables (Note that non-primitive variables are always references to objects in Java), the members of the referred object can be changed. final for non-primitive variables just mean that they cannot be changed to refer to any other object". geeksforgeeks.org/g-fact-48Electrolyte
Also valid, specially for mentioning as primitive and non-primitive cases. Tks.Scrutator
C
7

"A final variable can only be assigned once"

*Reflection* - "wowo wait, hold my beer".


Freeze of final fields happen in two scenarios:

  • End of constructor.
  • When reflection sets the field's value. (as many times as it wants to)

Let's break the law

public class HoldMyBeer 
{
    final int notSoFinal;
    
    public HoldMyBeer()
    {
       notSoFinal = 1;
    }

    static void holdIt(HoldMyBeer beer, int yetAnotherFinalValue) throws Exception
    {
       Class<HoldMyBeer> cl = HoldMyBeer.class;
       Field field = cl.getDeclaredField("notSoFinal");
       field.setAccessible(true);
       field.set(beer, yetAnotherFinalValue);
    }

    public static void main(String[] args) throws Exception 
    {
       HoldMyBeer beer = new HoldMyBeer();
       System.out.println(beer.notSoFinal);
       holdIt(beer, 50);
       System.out.println(beer.notSoFinal);
       holdIt(beer, 100);
       System.out.println(beer.notSoFinal);
       holdIt(beer, 666);
       System.out.println(beer.notSoFinal);
       holdIt(beer, 8888);
       System.out.println(beer.notSoFinal);
    }    
}

Output:

1
50
100
666
8888

The "final" field has been assigned 5 different "final" values (note the quotes). And it could keep being assigned different values over and over...

Why? Because reflection is like Chuck Norris, and if it wants to change the value of an initialized final field, it does. Some say he himself is the one that pushes the new values into the stack :

Code:
   7: astore_1
  11: aload_1
  12: getfield                
  18: aload_1
  19: bipush        50        //wait what
  27: aload_1
  28: getfield                
  34: aload_1
  35: bipush        100       //come on...
  43: aload_1
  44: getfield                
  50: aload_1
  51: sipush        666      //...you were supposed to be final...
  60: aload_1
  61: getfield                
  67: aload_1
  68: sipush        8888     //ok i'm out whatever dude
  77: aload_1
  78: getfield                
Calondra answered 30/1, 2021 at 20:4 Comment(1)
Check a related useful answer also.Lepp
S
4

final is a reserved keyword in Java to restrict the user and it can be applied to member variables, methods, class and local variables. Final variables are often declared with the static keyword in Java and are treated as constants. For example:

public static final String hello = "Hello";

When we use the final keyword with a variable declaration, the value stored inside that variable cannot be changed latter.

For example:

public class ClassDemo {
  private final int var1 = 3;
  public ClassDemo() {
    ...
  }
}

Note: A class declared as final cannot be extended or inherited (i.e, there cannot be a subclass of the super class). It is also good to note that methods declared as final cannot be overridden by subclasses.

Benefits of using the final keyword are addressed in this thread.

Sunder answered 17/2, 2014 at 2:5 Comment(1)
the value stored inside that variable cannot be changed latter is partially true. It is true for only primitive data types. In case of any object is made as final, like arraylist, its value can change but not the reference. Thank you!Tufa
L
2

First of all, the place in your code where you are initializing (i.e. assigning for the first time) foo is here:

foo = new ArrayList();

foo is an object (with type List) so it is a reference type, not a value type (like int). As such, it holds a reference to a memory location (e.g. 0xA7D2A834) where your List elements are stored. Lines like this

foo.add("foo"); // Modification-1

do not change the value of foo (which, again, is just a reference to a memory location). Instead, they just add elements into that referenced memory location. To violate the final keyword, you would have to try to re-assign foo as follows again:

foo = new ArrayList();

That would give you a compilation error.


Now, with that out of the way, think about what happens when you add the static keyword.

When you do NOT have the static keyword, each object that instantiates the class has its own copy of foo. Therefore, the constructor assigns a value to a blank, fresh copy of the foo variable, which is perfectly fine.

However, when you DO have the static keyword, only one foo exists in memory that is associated with the class. If you were to create two or more objects, the constructor would be attempting to re-assign that one foo each time, violating the final keyword.

Lytton answered 22/7, 2014 at 19:2 Comment(0)
S
2

Suppose you have two moneyboxes, red and white. You assign these moneyboxes only two children and they are not allowed interchange their boxes. So You have red or white moneyboxes(final) you cannot modify the box but you can put money on your box.Nobody cares (Modification-2).

Sheets answered 27/1, 2016 at 20:4 Comment(0)
M
2

Read all the answers.

There is another user case where final keyword can be used i.e. in a method argument:

public void showCaseFinalArgumentVariable(final int someFinalInt){

   someFinalInt = 9; // won't compile as the argument is final

}

Can be used for variable which should not be changed.

Myotome answered 27/6, 2017 at 23:48 Comment(0)
B
1
  1. Since the final variable is non-static, it can be initialized in constructor. But if you make it static it can not be initialized by constructor (because constructors are not static).
  2. Addition to list is not expected to stop by making list final. final just binds the reference to particular object. You are free to change the 'state' of that object, but not the object itself.
Bozuwa answered 27/3, 2013 at 9:3 Comment(0)
B
1

When you make it static final it should be initialized in a static initialization block

    private static final List foo;

    static {
        foo = new ArrayList();
    }

    public Test()
    {
//      foo = new ArrayList();
        foo.add("foo"); // Modification-1
    }
Bedrail answered 27/3, 2013 at 9:8 Comment(0)
Q
1

The final keyword indicates that a variable may only be initialized once. In your code you are only performing one initialization of final so the terms are satisfied. This statement performs the lone initialization of foo. Note that final != immutable, it only means that the reference cannot change.

foo = new ArrayList();

When you declare foo as static final the variable must be initialized when the class is loaded and cannot rely on instantiation (aka call to constructor) to initialize foo since static fields must be available without an instance of a class. There is no guarantee that the constructor will have been called prior to using the static field.

When you execute your method under the static final scenario the Test class is loaded prior to instantiating t at this time there is no instantiation of foo meaning it has not been initialized so foo is set to the default for all objects which is null. At this point I assume your code throws a NullPointerException when you attempt to add an item to the list.

Quash answered 27/3, 2013 at 9:9 Comment(0)
T
1

Following are different contexts where final is used.

Final variables A final variable can only be assigned once. If the variable is a reference, this means that the variable cannot be re-bound to reference another object.

class Main {
   public static void main(String args[]){
      final int i = 20;
      i = 30; //Compiler Error:cannot assign a value to final variable i twice
   }
}

final variable can be assigned value later (not compulsory to assigned a value when declared), but only once.

Final classes A final class cannot be extended (inherited)

final class Base { }
class Derived extends Base { } //Compiler Error:cannot inherit from final Base

public class Main {
   public static void main(String args[]) {
   }
}

Final methods A final method cannot be overridden by subclasses.

//Error in following program as we are trying to override a final method.
class Base {
  public final void show() {
       System.out.println("Base::show() called");
    }
}     
class Derived extends Base {
    public void show() {  //Compiler Error: show() in Derived cannot override
       System.out.println("Derived::show() called");
    }
}     
public class Main {
    public static void main(String[] args) {
        Base b = new Derived();;
        b.show();
    }
}
Thorpe answered 7/10, 2016 at 6:26 Comment(0)
A
1

I thought of writing an updated and in depth answer here.

final keyword can be used in several places.

  1. classes

A final class means that no other class can extend that final class. When Java Run Time (JRE) knows an object reference is in type of a final class (say F), it knows that the value of that reference can only be in type of F.

Ex:

F myF;
myF = new F();    //ok
myF = someOther;  //someOther cannot be in type of a child class of F.
                  //because F cannot be extended.

So when it executes any method of that object, that method doesn't need to be resolved at run time using a virtual table. i.e. run-time polymorphism cannot be applied. So the run time doesn't bother about that. Which means it saves processing time, which will improve performance.

  1. methods

A final method of any class means that any child class extending that class cannot override that final method(s). So the run time behavior in this scenario is also quite same with the previous behavior I mentioned for classes.

  1. fields, local variables, method parameters

If one specified any kind of above as final, it means that the value is already finalized, so the value cannot be changed.

Ex:

For fields, local parameters

final FinalClass fc = someFC; //need to assign straight away. otherwise compile error.
final FinalClass fc; //compile error, need assignment (initialization inside a constructor Ok, constructor can be called only once)
final FinalClass fc = new FinalClass(); //ok
fc = someOtherFC; //compile error
fc.someMethod(); //no problem
someOtherFC.someMethod(); //no problem

For method parameters

void someMethod(final String s){
    s = someOtherString; //compile error
}

This simply means that value of the final reference value cannot be changed. i.e. only one initialization is allowed. In this scenario, in run time, since JRE knows that values cannot be changed, it loads all these finalized values (of final references) into L1 cache. Because it doesn't need to load back again and again from main memory. Otherwise it loads to L2 cache and does time to time loading from main memory. So it is also a performance improvement.

So in all above 3 scenarios, when we have not specified the final keyword in places we can use, we don't need to worry, compiler optimizations will do that for us. There are also lots of other things that compiler optimizations do for us. :)

Ahrens answered 14/1, 2018 at 3:49 Comment(0)
C
0

Above all are correct. Further if you do not want others to create sub classes from your class, then declare your class as final. Then it becomes the leaf level of your class tree hierarchy that no one can extend it further. It is a good practice to avoid huge hierarchy of classes.

Cupola answered 23/12, 2013 at 2:10 Comment(0)
A
0

I can only say in answer to your question that in this case you can't change reference value of foo. You just simply put value into the same reference, that's why you can add value into the foo reference. This problem is occur you can't understand very well difference between reference value and primitive value. Reference value is also a value which store object address(this is value) in heap memory.

public static void main(String[] args) 
  {
      Test t = new Test();
      t.foo.add("bar"); // Modification-2
      System.out.println("print - " + t.foo);
  }

but in this case you can see that if you try to write in the following code you will see that compile time error will occur.

public static void main(String[] args)
{
    Main main = new Main();
    main.foo=new ArrayList<>();//Cannot assign a value to final variable 'foo'
    System.out.println("print - " + main.foo);
}
Acuate answered 22/5, 2022 at 19:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.