class Foo {
public Foo() { }
}
class Bar {
static Foo foo = new Foo(); // This is legal...
public static void main(String[] args) {
static int a = 0; // ... But why this is not?
}
}
为什么我们不能在静态函数内声明静态变量?
答案 0 :(得分:17)
您必须制作静态final static
或删除static
。
在Java中,static意味着它是类的变量/方法,它属于整个类,但不属于某个特定对象之一。这意味着静态关键字只能用于“范围”范围内。
通常,在C中,您可以静态分配本地范围的变量。不幸的是,这不是Java直接支持的。但是你可以通过使用嵌套类来实现相同的效果。
例如,允许以下内容,但这是糟糕的工程,因为x的范围远大于它需要的范围。此外,两个成员(x和getNextValue)之间存在非明显的依赖关系。
static int x = 42;
public static int getNextValue() {
return ++x;
}
人们真的想做以下事情,但这不合法:
public static int getNextValue() {
static int x = 42; // not legal :-(
return ++x;
}
但是你可以这样做,
public static class getNext {
static int x = 42;
public static int value() {
return ++x;
}
}
以牺牲一些丑陋为代价更好的工程。
答案 1 :(得分:11)
其他人已经解释了如何在编码层面处理这个问题。请允许我解释为什么静态方法没有意义的逻辑和哲学原因。你必须问一个问题“你希望变量能持续多久?”。
那么您希望“方法中的静态”变量持续多久?如果直到方法结束,那么你可以在没有静态的情况下使用它。如果它是类的生命周期,那么您可以将它声明为静态成员变量。还有哪些其他选择?
C ++允许方法中的静态,但它们最终表现得像静态类变量,但范围缩小。即使在C ++中,它们也很少使用。它们最终的存储方式与静态成员变量完全相同。这种模式被广泛认为是危险和令人困惑的,因为它让一个方法“记住”从一次调用看起来像一个局部变量的值到另一个 - 如果其他一些代码选择的话,这个值会被改变在两次调用之间执行该方法。
Java设计人员认为,少量的好处并不值得语言的额外复杂性。
答案 2 :(得分:4)
将变量声明为final,而不是静态。
静态意味着每个类有一个,而不是每个类的一个实例。最终意味着它不能在创建后进行修改。 (虽然请注意,创建引用final不会使它引用的类成为不可变的。)
换句话说,如果你有
final String[] array = new String[3];
您无法再更改该变量,例如,如果您想为其分配一个不同的大小的新阵列。但是,您可以修改数组的内容。
array[0] = "test";
因为这会修改内容,而不是数组本身。
同样适用于任何可变对象。
答案 3 :(得分:1)
方法中带有的变量是局部变量,其范围位于方法内,并且在执行方法后被销毁。即您不能在当前方法之外使用与类/静态变量的定义相矛盾的局部变量。 因此,在方法内声明静态变量毫无意义,如果您仍然尝试这样做,则会生成编译时错误,即(表达式的非法开头^ static int a = 0 )
答案 4 :(得分:0)
Java不允许用户在本地创建静态变量,因为在Java中,静态变量的作用域是全局的(即整个程序),因此没有必要在本地创建静态变量,因此为了避免歧义,Java不允许用户在本地创建静态变量。我们只能将静态变量创建为全局静态变量。
答案 5 :(得分:0)
我想您的期望是像一个static
局部变量那样的行为,该局部变量在C函数中具有初始化程序,该函数仅被初始化一次,即在函数的第一次调用中,而在以后的调用中没有。>
Java static
字段类似于C static
局部变量,因为静态字段仅初始化一次,即在加载类时初始化。
关于提及它的其他答案,final
与无关!
final
表示变量/字段的值在初始化后无法更改。
Java中的惯用解决方案首先不使用static
字段,除了常量以及诸如高速缓存和注册表之类的东西。
通常,更好的解决方案是编写一个新类,而不是将要保留在“ static
”变量中的值作为常规(非静态)字段保存。您可以在字段声明中或在新类的构造函数中对其进行初始化,然后使用(非静态)方法进行所需的计算。