How does the “final” keyword in Java work? (I can

2018-12-31 08:18发布

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?

标签: java final
18条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 08:36

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).

查看更多
流年柔荑漫光年
3楼-- · 2018-12-31 08:38

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.

查看更多
十年一品温如言
4楼-- · 2018-12-31 08:38

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

查看更多
一个人的天荒地老
5楼-- · 2018-12-31 08:40

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).

查看更多
倾城一夜雪
6楼-- · 2018-12-31 08:40

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
    }
查看更多
春风洒进眼中
7楼-- · 2018-12-31 08:41

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.

查看更多
登录 后发表回答