How does the “final” keyword in Java work? (I can still modify an object.)

前端 未结 18 2568
醉酒成梦
醉酒成梦 2020-11-22 03:08

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

18条回答
  •  南方客
    南方客 (楼主)
    2020-11-22 03:39

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

提交回复
热议问题