无法在静态方法中声明静态变量

时间:2014-06-17 16:50:29

标签: java

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?
    }
}

为什么我们不能在静态函数内声明静态变量?

6 个答案:

答案 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”变量中的值作为常规(非静态)字段保存。您可以在字段声明中或在新类的构造函数中对其进行初始化,然后使用(非静态)方法进行所需的计算。