最终变量value
的这两种初始化是否有区别?
class Test {
final int value = 7;
Test() {}
}
和
class Test {
final int value;
Test() {
value = 7;
}
}
,
EDIT:一个更复杂的例子,涉及子类。在这种情况下,"0"被打印到标准输出,但如果我直接赋值,则打印7。
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);
}
}
字节码级别不同:
源代码: final int value;
public TestBox() {
value = 7;
}
从addPropertyChangeListener
生成以下代码:
0: getstatic #3;
3: aload_0
4: getfield #2;
7: invokevirtual #4;
和源代码:
final int value = 7;
public TestBox() {
}
从addPropertyChangeListener
生成以下代码:
0: getstatic #3;
3: bipush 7
5: invokevirtual #4;
所以差别很小。但不实际。
如果在定义语句中初始化,编译器似乎可以将final变量作为常量处理。当然不同的编译器会有不同的处理方式
尝试了一个非常简单的例子,是的,当value在父类的构造函数中被访问时,它被初始化(应该是),除非它是final 和在声明时初始化。该过程与ejb描述的过程相同,但有一个#0步骤:如果有,则使用指定的值初始化final。
对final变量的一个常见误解是它不能改变它的值。final修饰符(JLS 4.5.4)的实际含义是"一个final变量只能被赋值一次"。
您遇到了这样一种情况,即可能对所谓的"blank final"(已声明,但尚未赋值)变量求值,以便它对指定的数据类型求值为默认值,即使稍后为其赋了不同的值。
除此之外,在第二种情况下,您可以根据调用构造函数或传递给它的参数分配不同的值,NO。
不,没有。唯一的区别是初始化字段的顺序:直接初始化的字段在构造函数中初始化的字段之前初始化。
我不认为有什么区别。但是你需要的值可能会帮助你决定使用哪个。
- 如果变量是final的,并且在构造函数中被赋了固定值,那么不需要在构造函数中赋值。
- 如果变量是final的,并且作为参数在构造函数中分配了不同的值,那么你需要在构造函数中分配它。
通常使用第一种情况。因为据我所知,final变量就是常量
构造函数按以下顺序执行:
- super()被调用。
- 初始化局部变量,调用匿名初始化块{}。
- 调用构造函数本身的代码。请注意,如果构造函数显式调用super()本身,则在#1中进行处理。
所以你的问题的答案是,初始化将从带初始化声明版本的#2移动到构造函数中初始化版本的#3。但是,除非您有匿名初始化块{}或可能使用其他字段的先前初始化来初始化的字段,否则无法区分它们。