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

Old*_*ool 15 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?
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Tin*_*a J 17

你必须做静态final static或删除static.

在Java中,static意味着它是类的变量/方法,它属于整个类,但不属于某个特定对象.这意味着static关键字只能在"类范围"中使用.

通常,在C中,您可以静态分配本地范围的变量.不幸的是,这不是Java直接支持的.但是通过使用嵌套类可以实现相同的效果.

例如,允许以下内容,但这是糟糕的工程,因为x的范围远大于它需要的范围.此外,两个成员(x和getNextValue)之间存在非明显的依赖关系.

static int x = 42;
public static int getNextValue() {
    return ++x;
}
Run Code Online (Sandbox Code Playgroud)

人们真的想做以下事情,但这不合法:

public static int getNextValue() {
    static int x = 42;             // not legal :-(
    return ++x;
}
Run Code Online (Sandbox Code Playgroud)

不过你可以这样做,

public static class getNext {
    static int x = 42; 
    public static int value() {
        return ++x;
    }
}
Run Code Online (Sandbox Code Playgroud)

以牺牲一些丑陋为代价是更好的工程.

  • 仅仅因为Java不允许它并不意味着`static`不能"在方法内部有任何意义".当然可以,例如,`static int getNextCounter(){static int x = 0; return x ++; }`可以返回增加的值,你可以确信没有其他方法可以修改'x`,因为它只有该方法的范围.仅仅因为语言中没有包含某些内容并不意味着它没有任何意义. (14认同)
  • “更好的工程以牺牲一些丑陋为代价”似乎是 Java 中的一个常见主题,尽管“更好的工程”是有争议的。 (2认同)

DJC*_*rth 13

其他人已经解释了如何在编码级别处理这个问题.请允许我解释为什么静态方法没有意义的逻辑和哲学原因.你必须问一个问题"你希望变量能持续多久?".

  • 普通成员变量只要它们所属的实例持续;
  • 在方法退出之前,在方法中声明的变量;
  • 静态类变量持续为类的生命周期(即永远用于大多数目的)

那么你希望你的'方法中的静态'变量持续多久?如果直到方法结束,那么你可以在没有静态的情况下使用它.如果它是类的生命周期,那么您可以将它声明为静态成员变量.还有哪些其他选择?

C++允许在方法中使用静态,但它们最终表现得像静态类变量,但范围缩小.即使在C++中,它们也很少使用.它们最终的存储方式与静态成员变量完全相同.这种模式被广泛认为是危险和令人困惑的,因为它让一个方法"记住"从一次调用看起来像一个局部变量的值到另一个 - 如果其他一些代码选择的话,这个值会被改变在两个调用之间执行该方法.

Java设计者认为,少量的好处不值得语言的额外复杂性.

  • "如果它是在类的生命周期中,那么你可以将它声明为静态成员变量.还有哪些其他选项?" 但是你没有得到的是保证类中的其他方法不会修改它.这就是方法中的静态变量会给你(正如你所指出的):范围有限.有限的范围使*更容易*推理程序的行为. (8认同)

Tim*_*m B 3

将变量声明为最终变量,而不是静态变量。

静态意味着每个类都有一个,而不是该类的每个实例都有一个。Final表示创建后不能修改。(尽管请注意,将引用设为 Final 并不会使它引用的类变得不可变)。

换句话说,如果你有一个

final String[] array = new String[3];
Run Code Online (Sandbox Code Playgroud)

您无法再更改该变量,例如,如果您想为其分配一个不同大小的新数组,则无法更改。但是您可以修改数组的内容。

array[0] = "test";
Run Code Online (Sandbox Code Playgroud)

因为这会修改内容,而不是数组本身。

同样的事情也适用于任何可变对象。