2012-03-11 15 views
0
  1. 为什么final变量默认初始化?如果你对这个常量是默认值感到满意,那么默认构造函数不应该将它们初始化为默认值。限制最终变量分配的原因

  2. 为什么你必须在构造函数中初始化它们?为什么你不能在使用它们之前像其他变量一样初始化它们?

ex。

public class Untitled { 

public final int zero; 

    public static void main(String[] args) 
    { 
      final int a; // this works 
      a = 4; // this works, but using a field doesn't 
      new Untitled(); 
    } 
} 

Untitled.java:2: variable a might not have been initialized 
  1. 为什么你必须初始化变量static final他们在声明时?为什么不能在用任何其他方法使用它们之前对它们进行初始化?

ex。

public class Untitled 
{ 

     public final static int zero; 

     public static void main(String[] args) 
     { 
      zero = 0; 
     } 
} 

Untitled.java:8: cannot assign a value to final variable zero 

我在问这些问题,因为我试图找到一个逻辑/概念的原因,为什么这不起作用,为什么它不被允许。不仅仅因为它不是。

+0

请记住,'主()'是*不*构造函数。很明显,你不能在一个不是构造函数的方法中分配一个'final'变量。 – 2012-03-11 02:22:18

回答

3

变量final背后的想法是它只设置一次而已。

例如final变量,这意味着它们只能在初始化期间在声明进行设置,是否,在一个构造函数,或一个实例初始化块。要在其他地方设置变量,这必须在非构造函数方法中进行,该方法可以多次调用 - 这就是为什么这是无限制的。

类似地,对于static final变量,它们只能在声明或在静态初始化块设置。要是在别的地方会再次必须在一个可称为多,一旦方法:

public static void main(String[] args) 
{ 
    zero = 0; 
    main(null); 
} 

关于你提到的第一个问题,我假设这是一个错误不明确,为了设置一个final变量避免程序员的错误。

+0

这实际上很有意义。我没有考虑到这一点,我会接受这个答案:-) – rubixibuc 2012-03-11 02:31:32

+0

如果你有多个构造函数,他们都可以设置最终实例字段的值。在单个构造函数或init块中,可以有多个赋值(例如,'if(something){x = 1;} else {x = 2;}'因此,编译器不会以不同于静态或实例字段的方式处理最终局部变量 – emory 2012-03-11 02:53:27

+0

@emory - 你说的对,要清楚的是,在所有情况下,每个代码路径只能有一个赋值(或“throw”),OP在备注中想知道的是为什么本地'final '变量可以取消赋值,不像'final'字段。但是我的编辑没有真正回答 - 我会删除它。 – 2012-03-11 03:13:26

0

正在最后的概念意味着变量值不能改变。如果你可以像你的第二个例子那样做,那么这个变量就像任何其他变量一样(即不是最终的)

我对你的第一个问题没有很好的理性。

+0

我在Java中遇到的问题是,如果我像上面所做的那样将它声明为局部变量,它就会起作用。我不明白使用最终字段或最终局部变量 – rubixibuc 2012-03-11 02:27:03

1

Java Language Specification section 8.3.1.2的阐明了final成员变量的规则:

字段可以声明final(§4.12.4)。类和实例变量(static和非static字段)都可以声明为final。

它是一个编译时间错误,如果空白final(§4.12.4)类变量没有明确的一个static初始化(§16.8)分配在其中它被声明的类的(§8.7)。

空白final实例变量必须在声明类的每个构造函数(第8.8节)末尾明确赋值(第16.9节);否则会发生编译时错误。

JLS不给出理由为什么规则是他们的方式。但是,它可能来自编写Java代码的经验,上述规则是避免一些常见编码错误的一种方法。

+0

我知道这些规则,我不明白他们为什么这样做。我试图理解它在机械层面如何处理它。 – rubixibuc 2012-03-11 02:29:44

0

因为在查看代码时,Java编译器不知道给定语句是否会在其他语句之前执行。这条规则的唯一例外是构造函数和隐式构造函数中的代码,这就是为什么它们是唯一可以分配最终字段的地方。

+0

什么是隐式构造函数?我对这个词不熟悉。你指的是一个init块,如'class X {int x; {x = 10; }}'? – emory 2012-03-11 02:57:31