在var初始化期间使用this.var

时间:2013-04-05 08:18:22

标签: java initialization undefined-behavior

在研究another question时,我惊讶地发现以下Java代码编译时没有错误:

public class Clazz {
    int var = this.var + 1;
}

在我的JDK6中,var被初始化为1

上面的代码是否具有明确定义的语义,或者它的行为是否未定义?如果您说它定义明确,请引用JLS的相关部分。

6 个答案:

答案 0 :(得分:4)

section 8.3.2.3中的例子8.3.2.3-1中提到了它。在示例的文本中

class Z {
    static int peek() { return j; }
    static int i = peek();
    static int j = 1;
}
class Test {
    public static void main(String[] args) {
        System.out.println(Z.i);
    }
}
标题说:

  

... i的变量初始化器使用类方法peek在其变量初始化器初始化j之前访问变量j 的值,此时它仍然具有其默认值( §4.12.5)即可。

这应该直接映射到您的情况。

答案 1 :(得分:3)

Chapter 8.3.2.2. paragraph 2

  

允许实例变量的初始化表达式引用当前对象this(§15.8.3)并使用关键字super(§15.11.2,§15.12)。

虽然下一段增加了:

  

使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此。有关控制实例变量的正向引用的精确规则,请参见§8.3.2.3。

答案 2 :(得分:0)

Introduction of Chapter 16

  

第16章描述了语言确切的确切方式   在使用之前肯定设置了局部变量。所有其他   变量自动初始化为默认值Java   编程语言不会自动初始化局部变量   为了避免掩盖编程错误。

答案 3 :(得分:0)

forward references根据JSL,不允许使用简单名称。 因此,必须使用 关键字来访问此类变量。

class UseBeforeDeclaration {
    int h = j++;  // error - `j` read before declaration
    int l = this.j * 3;  // ok - not accessed via simple name
    int j;
}

答案 4 :(得分:0)

由于所有非局部变量都被分配了一个初始值(并且分配发生在其他所有变量之前),所以在任何时候都可以读取它们。

规范在某些情况下有选择地禁止某些访问,推断这种访问很可能是编程错误。但如果允许这些访问,它们将具有明确定义的语义。

实际上程序员可以轻松绕过限制并“间接”访问该领域;如果允许,该访问的语义与“直接”访问相同。

int var = this.var + 1;       // suppose javac forbids this

int var = this.getVar() + 1;  // but can javac forbid this?

答案 5 :(得分:-1)

这没什么错。此关键字引用当前对象,它用于区分局部变量和实例变量。局部变量的值可以同样地分配给实例变量,反之亦然。这意味着我们可以将实例变量的值分配给局部变量。

请参阅http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf(第80页)中的 4.12.3变量种类一章。这里也举了一个例子。

      **Example 4.12.3-1. Different Kinds of Variables**
      class Point { 
      static int numPoints; // numPoints is a class variable 
      int x, y; // x and y are instance variables 
      int[] w = new int[10]; // w[0] is an array component 
      int setX(int x) { // x is a method parameter 
        int oldx = this.x; // oldx is a local variable 
        this.x = x; 
        return oldx; 
      } 
    }