在研究another question时,我惊讶地发现以下Java代码编译时没有错误:
public class Clazz {
int var = this.var + 1;
}
在我的JDK6中,var
被初始化为1
。
上面的代码是否具有明确定义的语义,或者它的行为是否未定义?如果您说它定义明确,请引用JLS的相关部分。
答案 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)
允许实例变量的初始化表达式引用当前对象this(§15.8.3)并使用关键字super(§15.11.2,§15.12)。
虽然下一段增加了:
使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此。有关控制实例变量的正向引用的精确规则,请参见§8.3.2.3。
答案 2 :(得分:0)
第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;
}
}