这是我的代码:
class StaticBlock {
{
println("initializer block : " + message);
}
public StaticBlock(String message) {
this.message = message;
}
private String message;
}
现在的问题是,在初始化程序块
中{
println("initializer block : " + message);
}
如果我在this
之前添加message
关键字,则可行,但错误this
关键字时会出错。
编译器说:
StaticBlockDemo.java:34: illegal forward reference
println("initializer block : " + message);
^
1 error
为什么他们不一样?
答案 0 :(得分:5)
我不知道设计原理,但它可能有助于阅读Java语言规范的相关部分。
允许实例初始值设定项通过关键字
this
(第15.8.3节)引用当前对象,以使用关键字super
(§15.11.2,§15.12),并使用范围内的任何类型变量。使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此。有关控制实例变量的正向引用的精确规则,请参见§8.3.2.3。
8.3.2.3. Restrictions on the use of Fields during Initialization
成员声明只有在成员是类或接口
static
的实例(分别为C
)字段并且满足以下所有条件时才需要以文本方式显示:
用法发生在
static
的实例(分别为C
)变量初始值设定项或C
的实例(分别为静态)初始值设定项中。用法不在作业的左侧。
用法是通过一个简单的名称。
C
是封闭用法的最内层的类或接口。
以下是修剪规范部分的示例,以说明您所询问的具体问题:
class UseBeforeDeclaration {
{
j = 200;
// ok - assignment
j = j + 1;
// error - right hand side reads before declaration
int k = j = j + 1;
// error - illegal forward reference to j
int n = j = 300;
// ok - j at left hand side of assignment
int h = j++;
// error - read before declaration
int l = this.j * 3;
// ok - not accessed via simple name
}
int j;
}
但是,我应该注意,即使是代码的编译版本也不会做你想要的。如果你运行它:
new StaticBlock("abc");
会打印
initializer block : null
这是因为初始化程序在构造函数体之前(大部分)执行。以下是规范中的重点:
12.5. Creation of New Class Instances
[...] 处理指示的构造函数以使用以下过程初始化新对象:
[...]
4.为此类执行实例初始值设定项和实例变量初始值设定项 [...]
5.执行此构造函数的其余部分。 [...]
答案 1 :(得分:0)
如果我在'message'之前添加'this'关键字,它可以正常工作,但在错过'this'关键字时会出错。为什么他们不一样?
this
个关键字指向该类的当前实例。
public StaticBlock(String message) {
this.message = message;
}
如果您不使用this
,那么它将分配message
局部变量的值,因为局部变量的范围大于块中的实例。
当您使用this
时,它将分配当前对象变量的变量值。
答案 2 :(得分:0)
如果局部变量名和实例成员名之间存在冲突,那么编译器将this
关键字告诉使用对象变量。
答案 3 :(得分:0)
在Java中使用类的一个好处是,您可以将对象建模为类,并且可以创建对象的多个实例(在大多数情况下)。
为了引用特定于单个对象类的信息,我们可以在对象(类)代码中使用this
。它告诉程序您要使用current
个对象变量和值。通过使用this.message = message
,您将分配已传递给函数的消息值并将其存储在对象的消息变量中。
这有范围方面,其中message
具有局部范围,this.message
具有整个对象的范围。这就是为什么当您尝试在打印代码中调用消息时println("initializer block : " + message);
,在此函数的范围内不存在本地变量消息。