简体   繁体   English

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

[英]Unable to declare static variable inside of static method

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

Why can't we declare a static variable inside of a static function?为什么我们不能在静态函数内部声明静态变量?

You have to make the static final static or remove static .您必须使 static final static或删除static

In Java, static means that it's a variable/method of a class, it belongs to the whole class but not to one of its certain objects.在 Java 中,静态意味着它是一个类的变量/方法,它属于整个类但不属于其某些对象之一。 This means that static keyword can be used only in a 'class scope'.这意味着 static 关键字只能在“类范围”中使用。

Generally, in C, you can have statically allocated locally scoped variables.通常,在 C 中,您可以静态分配局部范围的变量。 Unfortunately this is not directly supported in Java.不幸的是,这在 Java 中并不直接支持。 But you can achieve the same effect by using nested classes.但是您可以通过使用嵌套类来达到相同的效果。

For example, the following is allowed but it is bad engineering, because the scope of x is much larger than it needs to be.例如,下面是允许的,但它是糟糕的工程,因为 x 的范围比它需要的要大得多。 Also there is a non-obvious dependency between two members (x and getNextValue).此外,两个成员(x 和 getNextValue)之间也存在不明显的依赖关系。

static int x = 42;
public static int getNextValue() {
    return ++x;
}

One would really like to do the following, but it is not legal:一个人真的很想做以下事情,但这是不合法的:

public static int getNextValue() {
    static int x = 42;             // not legal :-(
    return ++x;
}

However you could do this instead,但是你可以这样做,

public static class getNext {
    static int x = 42; 
    public static int value() {
        return ++x;
    }
}

It is better engineering at the expense of some ugliness.它是以牺牲一些丑陋为代价的更好的工程。

Other people have explained how to deal with this at the coding level.其他人已经解释了如何在编码级别处理这个问题。 Allow me to explain the logical and philosophical reasons why static within a method makes no sense.请允许我解释为什么方法中的静态没有意义的逻辑和哲学原因。 You have to ask the question "How long do you want the variable to last?".您必须问“您希望变量持续多长时间?”的问题。

  • normal member variables last as long as the instance they are part of;普通成员变量的持续时间与它们所属的实例一样长;
  • variables declared within a method last until the method is exited;在方法中声明的变量一直持续到方法退出;
  • static class variables last for the lifetime of the class (ie forever for most purposes)静态类变量在类的生命周期内持续(即对于大多数用途来说是永远的)

So how long do you want your 'static within a method' variable to last?那么,您希望“方法内的静态”变量持续多长时间? If it's until the end of the method, then you can just use it without static.如果一直到方法结束,那么您可以直接使用它而不使用静态。 If it's for the lifetime of the class, then you can declare it as a static member variable.如果是在类的生命周期内,则可以将其声明为静态成员变量。 What other options are there?还有哪些其他选择?

C++ allows statics within a method, but they end up behaving just like a static class variable, but with reduced scope. C++ 允许在方法中使用静态,但它们最终的行为就像静态类变量一样,但范围缩小了。 Even in C++ they are rarely used.即使在 C++ 中,它们也很少使用。 They also end up being stored exactly like static member variables.它们最终也完全像静态成员变量一样存储。 The pattern is widely considered to be dangerous and confusing, because it mounts to having a method 'remember' the value of what looks like a local variable from one invocation to another - a value which would be changed if some other piece of code chooses to execute the method in between the two invocations.该模式被广泛认为是危险和令人困惑的,因为它使方法“记住”从一次调用到另一次调用的局部变量的值 - 如果其他代码选择该值,该值将被更改在两次调用之间执行该方法。

The Java designers decided that the small amount of benefit wasn't worth the additional complexity of the language. Java 设计者认为,少量的好处不值得语言的额外复杂性。

Declare the variable as final, not as static.将变量声明为最终变量,而不是静态变量。

Static means that there is one per class not one per instance of the class.静态意味着每个类有一个,而不是类的每个实例一个。 Final means it can't be modified after creation. Final 表示创建后无法修改。 (Although note that making a reference final does not make the class it references immutable). (尽管请注意,使引用最终不会使其引用的类不可变)。

In other words if you have a换句话说,如果你有一个

final String[] array = new String[3];

You can no longer change that variable, for example if you wanted to assign to it a new array with a different size you could not.您不能再更改该变量,例如,如果您想为其分配一个大小不同的新数组,则无法更改。 However you can modify the contents of the array.但是,您可以修改数组的内容。

array[0] = "test";

Because this modifies the contents, not the array itself.因为这会修改内容,而不是数组本身。

The same thing holds for any mutable objects.同样的事情也适用于任何可变对象。

Java doesn't allow user to create static variable locally as in java static variable's scope is global(ie throughout the program ) so there is no point of creating static variable locally thus in order to avoid ambiguousness java doesn't allow user to create static variable locally. Java 不允许用户在本地创建静态变量,因为在 Java 中静态变量的范围是全局的(即在整个程序中),因此没有必要在本地创建静态变量,因此为了避免歧义,Java 不允许用户创建静态变量局部变量。 We only can create static variable as global static variable .我们只能创建静态变量作为全局静态变量。

I suppose that your expectation was behaviour like a static local variable with an initializer in a C function, which is initialized only once, namely in the first call of the function, but not in subsequent calls.我想您的期望是像 C 函数中带有初始化程序的static局部变量一样的行为,它只初始化一次,即在函数的第一次调用中,而不是在后续调用中。

Java static fields is similar to C static local variables in that static fields are initialized only once, namely when the class is loaded. Java static字段类似于 C static局部变量,因为静态字段仅初始化一次,即在加载类时。

Regarding the other answers mentioning it, final has nothing to do with this!关于提到它的其他答案, final与此无关 final means that the value of a variable/field cannot be changed after it has been initialized. final表示变量/字段的值在初始化后不能更改。

The idiomatic solution in Java is not using static fields in the first place, except for constants and things like caches and registries. Java 中惯用的解决方案首先不使用static字段,除了常量和诸如缓存和注册表之类的东西。

Often, a better solution is to write a new class instead that holds the value you would wanted to keep in the " static " variable as a regular (non-static) field.通常,更好的解决方案是编写一个新类,而不是保存您希望作为常规(非静态)字段保留在“ static ”变量中的值。 You can initialize it in the field declaration or in the new class's constructor, and then do the computation you wanted to do in a (non-static) method.您可以在字段声明或新类的构造函数中对其进行初始化,然后在(非静态)方法中进行您想要进行的计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM