考虑:
int a = 0;
int b = 3;
//Constructor 1
public ClassName (int a) {
this(a, b); //Error
//new ClassName(a, b) //No error
}
//Constructor 2
public ClassName (int a, int b) {
this.a = a;
this.b = b;
}
第一个问题:
我收到错误消息“b应该是静态的”。为什么我不能以这种方式使用b的默认值(3)?
第二个问题:
在第一个构造函数中,如果我使用注释部分,我不会收到错误。这是否可以接受?
答案 0 :(得分:12)
the JLS, Section 8.8.7.1禁止在显式构造函数调用中使用实例变量。
构造函数体中的显式构造函数调用语句可能不引用此类或任何超类中声明的任何实例变量或实例方法或内部类,或者在任何表达式中使用
this
或super
;否则,发生编译时错误。禁止使用当前实例解释了为什么显式构造函数调用语句被认为是在静态上下文中发生的(第8.1.3节)。
您引用了实例变量b
。编译器没有在a
上引发此错误,因为它是一个局部变量,它会影响实例变量a
。
“静态上下文”可能是您的IDE建议使b
静态的原因,因此可以引用它。这说得通;对象的ClassName
部分尚未构建。将b
的用法替换为其他内容,例如static
常量或文字int
值。
要回答您的其他问题,键入new ClassName(a, b)
不是错误,因为此时已构建此实例,并且您正在创建一个单独的,不相关的ClassName
对象。
答案 1 :(得分:6)
第一个问题:我收到错误说" b应该是静态"。为什么我不能以这种方式使用b的默认值(3)?
向b
提供其他构造函数的默认值的正确方法是this(a, 3);
。在 this(...)
之后之前,您无法引用实例变量。这只是该语言规则之一。
第二个问题:在第一个构造函数中,如果我使用注释部分,我不会收到错误。这是否可以接受?
new ClassName(a, b);
做了不同的事情。它创建了一个单独的类实例。以我的拙见,这可能不是最好的事情。人们期望new
创建一个类的实例,而在构造函数中使用new ClassName
创建两个。
答案 2 :(得分:0)
在类中使用变量时,重要的是要注意范围的有效性。你已经在那里实例化了变量的新的a,b变体。你在欺骗自己相信那些变量是相同的。实际上他们在另一个地址空间。如果要使用类变量,则必须将参数取出到函数中。然后它们将与您所在的类同步,而不是将参数a,b隔离到函数范围内,