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

Is there a difference between the 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" prints to stdout in this case, but 7 prints 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); } } 
+6
source share
7 answers

I tried with a very simple example and yes, when the value is available in the parent constructor, it is unified (as it should be), unless it is declared final even when declared. This process is described by EJP, but in increments of # 0: the finals are initialized with the specified value, if any.

+2
source

There is a difference in the bytecode:

Source:

  final int value; public TestBox() { value = 7; } 

addPropertyChangeListener following code from addPropertyChangeListener :

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

And the source code:

 final int value = 7; public TestBox() { } 

addPropertyChangeListener following code from addPropertyChangeListener :

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

So there is a slight difference. But not practical.

It seems that the compiler can treat the final variable as a constant if it is intuitively defined in the definition. Of course, different compilers can do this differently.

+4
source

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

You are faced with one of the situations when it is possible to evaluate the so-called "empty final" (declared, but not yet assigned) variable so that it evaluates the default value for the specified data type, even if it was later assigned a different value.

+1
source

Another thing is that in the second case, you can assign a different value based on which constructor was called or what parameters were passed to it, NO.

0
source

No no. The only difference is the order used to initialize the fields: initialized fields are initialized before initialization in the constructor.

0
source

I don’t think there is any difference. But the value you need can help you decide what to use.

  • If the variable is final and assigned with a fixed value in the constructor, then there is no need to assign it in the constructor.
  • If the variable is final and assigned with different values ​​passed as an argument in the constructor, then you need to assign it in the constructor.

The first case is mainly used. Because, as far as I know, final varibales are nothing but constants.

0
source

The constructor is executed in the following order:

  • Called
  • super ().
  • Local variables are initialized and call the anonymous initializer blocks {}.
  • The code in the constructor is called. Note that if the constructor explicitly calls super (), this will be taken care of under # 1.

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

0
source

Source: https://habr.com/ru/post/902914/


All Articles