我正在准备JavaOCA认证,遇到了一个类似的问题,如下所示:
public class TestClass {
final int i;
public static void main(String[] args) {
TestClass t = new TestClass();
System.out.println(t.i);
}
}
按照Java,实例和静态变量被赋予默认值。令人惊讶的是,我的控制台上显示的错误是:
error: variable i not initialized in the default constructor final int i;
为什么i
没有在上面分配默认值?
并不是最终字段没有初始化为默认值——事实上它们是这样的,尽管你只有在做一些愚蠢的事情时才会观察到这个事实——而是你需要明确地初始化它们一次(作为声明的一部分,或者在初始化程序块中,或者在每个构造函数中)。
要理解这样做的动机,请考虑下面的代码:
public class Foo {
private final int mValue;
public Foo(final boolean shouldSet) {
if (shouldSet) {
mValue = 1;
}
}
// ...
}
如果该字段不是final,那么编译器会在其声明的末尾推断出一个隐式的< code > = 0 ;但是最后一个字段并不总是有效。。。而在上面的例子中,编译器甚至无法事先判断它是否会有效。因此,编译器通过从不推断隐式< code>= 0并要求显式初始化来回避这个问题。
在Java语言规范中是这样定义的:
每个局部变量(§14.4)和每个空白最终
字段(§4.12.4,§8.3.1.2)在访问其值时必须有明确的赋值。
[...]
对于局部变量或空白最终字段x的每次访问,必须在访问之前明确指定x,否则会发生编译时错误。
其中术语“blankfinal
field”指的是没有值或初始值设定项的final字段,“明确分配”表示无论发生什么情况,都将分配该字段:
确定赋值背后的想法是,对局部变量或空白最终
字段的赋值必须发生在访问的每个可能的执行路径上。类似地,确定取消分配背后的想法是,在任何可能的执行路径上都不允许对空白最终变量进行任何其他赋值。
除了通过规范抛出错误之外,决策背后还有逻辑推理。空的< code>final字段没有任何意义。在您的例子中,空白的< code>final是一个整数,它将被赋予0,您不能更改它。变量的用途是什么?
此外,如果<code>final
为<code>finalfinal
表示一旦赋值,就不能更改值。如果为最终变量指定了默认值,则永远无法将变量的值设置为其他值(即使是第一次)。
问题内容: 为什么在类中声明的变量具有默认值,但是在方法内部声明的变量(称为“局部变量”)在Java中没有默认值? 例如 在上面的示例中,变量的默认值为0,但是变量给出了可能尚未初始化的错误。 问题答案: 所有成员变量都必须加载到堆中,因此在创建类的实例时必须使用默认值进行初始化。对于局部变量,它们不会被加载到堆中,直到在Java7之前被使用,它们才会存储在堆栈中,因此我们需要显式初始化它们。现在
我有一个这样的程序: 如果我尝试执行它,我会得到如下编译器错误:< code >变量x可能没有初始化基于java默认值,我应该得到下面的输出对吗?? 最终变量会有默认值吗? 如果我这样更改代码, 我得到的输出是: 有人能解释一下这种行为吗。。
问题内容: 请参阅下面的代码,其中的方法被覆盖,但变量没有被覆盖。为什么允许在子类中声明重复的变量? 问题答案: 为什么在子类方法中不覆盖超类的实例变量,请参见下面的代码… 因为实例变量不能在Java中覆盖。在Java中,只能重写方法。 当你声明一个与超类中现有字段同名的字段时,新字段将隐藏现有字段。超类中的现有字段仍存在于子类中,甚至可以使用…遵守常规的Java访问规则。 因为实例变量在Java
问题内容: 我对背后似乎是不一致的原因感到困惑。 例如 因此,将按预期打印出0。但是说我们有这个 抱怨a尚未初始化,因此无法为我编译。我期望它能打印出0 … 这使我想到了一些问题: 1)为什么作用域变量没有默认值? 2)请问static关键字是原因吗?又为什么呢 问题答案: Java语言规范解释了变量的默认初始值 每个类变量,实例变量或数组组件在创建时都会用默认值初始化(第15.9节,第15.10
本文向大家介绍Python实例变量的默认值,包括了Python实例变量的默认值的使用技巧和注意事项,需要的朋友参考一下 示例 如果变量包含不可变类型的值(例如字符串),则可以分配这样的默认值 在初始化可变对象(例如构造函数中的列表)时,需要小心。考虑以下示例: 此行为是由于以下事实引起的:在Python中,默认参数是在函数执行时绑定的,而不是在函数声明时绑定的。要获得实例之间不共享的默认实例变量,
问题内容: 我读到Java为类属性提供了默认值,但没有为局部变量提供默认值。那是对的吗?如果是这样,背后的原因是什么?当您做某件事时,为什么不一直这样做呢? 谢谢你, 罗杰 问题答案: 标准局部变量存储在堆栈中,直到初始化后才真正创建。如果未使用局部变量,则它不会进入堆栈。但是,成员变量在堆中分配,因此具有默认的占位符(空引用或默认原语)。