10

在研究另一个问题时,我惊讶地发现以下 Java 代码编译时没有错误:

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

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

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

4

6 回答 6

4

在 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) 。

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

于 2013-04-05T10:12:56.977 回答
3

第 8.3.2.2 章。第 2 段

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

虽然下一段补充说:

有时限制使用在使用后以文本形式出现声明的实例变量,即使这些实例变量在范围内。有关管理对实例变量的前向引用的精确规则,请参见第 8.3.2.3 节。

于 2013-04-05T08:54:15.273 回答
0

第16章介绍

第 16 章描述了语言确保在使用前明确设置局部变量的精确方法。虽然所有其他变量都会自动初始化为默认值,但 Java 编程语言不会自动初始化局部变量以避免掩盖编程错误。

于 2013-04-05T08:30:11.053 回答
0

在按照JSL的情况下,不允许使用简单名称。所以必须使用这个关键字来访问这些变量。forward references

class UseBeforeDeclaration {
    int h = j++;  // error - `j` read before declaration
    int l = this.j * 3;  // ok - not accessed via simple name
    int j;
}
于 2013-04-05T11:07:51.053 回答
0

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

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

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

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

int var = this.getVar() + 1;  // but can javac forbid this?
于 2013-04-05T16:54:47.307 回答
-1

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

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

      **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; 
      } 
    }
于 2013-04-05T09:20:17.873 回答