简体   繁体   中英

Is there a difference between directly assigning a final variable and assigning a final variable in the constructor?

is there a difference between these two initializations of the final variable value ?

class Test {
    final int value = 7;
    Test() {}
}

and

class Test {
    final int value;
    Test() {
        value = 7;
    }
}

--

EDIT: A more complex example, involving subclasses. "0" is printed to stdout in this case, but 7 is printed if i assign the value directly.

import javax.swing.*;
import java.beans.PropertyChangeListener;

class TestBox extends JCheckBox {

    final int value;

    public TestBox() {
        value = 7;
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        System.out.println(value);
        super.addPropertyChangeListener(l); 
    }

    public static void main(String... args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        frame.setContentPane(panel);
        panel.add(new TestBox());
        frame.pack();
        frame.setVisible(true);
    }
}

There is differece in byte-code level:

Source code:

  final int value;

  public TestBox() {
      value = 7;
  }

Produces following code from addPropertyChangeListener :

   0:   getstatic       #3; 
   3:   aload_0
   4:   getfield        #2; 
   7:   invokevirtual   #4; 

And source code:

final int value = 7;

public TestBox() {      
}

Produces the following code from addPropertyChangeListener :

   0:   getstatic       #3; 
   3:   bipush  7
   5:   invokevirtual   #4; 

So there is a small difference. But not practical.

Seems that compiler can handle a final variable as a constant if it is intialized in definition statement. Of course different compilers may do it different way.

Tried with a very simple example and yes, when value is accessed in the parent's constructor it is unitialized (as it should be), unless it's final and initialized when declared. The process is that described by EJP, but with a #0 step: finals are initialized with the specified value, if any.

A common misinterpretation of a final variable is that it can't change its value. The actual meaning of the final modifier (JLS 4.5.4) is that "a final variable may only be assigned to once".

You've run into one of the situations where it is possible to evaluate a so called "blank final" (declared, but not yet assigned) variable, so that it evaluates to the default value for the specified datatype, even if its later assigned a different value.

其他在第二种情况下,您可以根据调用的构造函数或传递给它的参数指定不同的值, NO。

No, there is not. The only difference is the order used to initialize the fields: fields initialized directly are initialized before the ones initialized in the constructor.

I don't think there are any difference. But the value you need in it might help you in decide which to use.

  1. If the variable is final and assigned with fixed value in constructor then no need to assign it in constructor.
  2. If the variable is final and assigned with different values, passed as argument, in constructor then you need to assign it in constructor.

Mostly the first case is used. Because as far as I know final varibales are nothing but the constants.

A constructor executes in the following order:

  1. super() is called.
  2. Local variables are initialized and anonymous initializer blocks {} are called.
  3. The code in the constructor itself is called. Note that if the constructor explicitly calls super() itself this is taken care of under #1.

So the answer to your question is that the initialization would be moved from #2 in the declaration-with-initializer version to #3 in the initialize-in-constructor version. However unless you have anonymous initializer blocks {} or possibly fields that are initialized using prior initializations of other fields, it would be impossible to tell the difference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM