Java 中的 final 变量是否需要使用 "static" 关键字?

Is there any need to use "static" keyword for final variables in Java?

我对Java中的finalstatic关键字感到困惑,需要澄清以下问题:

1.变量有没有必要用static?例如:

public final int ERROR_CODE = 200;

我觉得没必要用static如下图。我错了吗?

public static final int ERROR_CODE = 200;

2. 据我所知,静态对于方法是有意义的,类 可以在不创建实例的情况下使用它们。 BUT,同样在这个静态方法中使用一个static变量,同时改变它们的值也是有意义的:

public class MyClass {
    public static int myVariable = 0; 
}

//Now in some other code creating two instances of MyClass
//and altering the variable will affect all instances

MyClass instance1 = new MyClass();
MyClass instance2 = new MyClass();

MyClass.myVariable = 5;  //This change is reflected in both instances


3. 我可以更改 final 和 static 关键字的顺序,例如

public static final int ERROR_CODE = 200; 

public final static int ERROR_CODE = 200; 

staticfinal是不同的概念。 static 成员属于 class 而不是实例,而您不能重新分配 final 变量。

MyClass.myVariable = 5; //This change is reflected in both instances

➡️ 如果 myVariable 被声明 final 就不可能了。

Can I change the order of final and static keywords e.g.

public static final int ERROR_CODE = 200; or

public final static int ERROR_CODE = 200;

➡️是的。这没有任何区别。

#1 用文字初始化一个非静态最终变量:

class MyClass {
   public final int ERROR_CODE = 200;
}

一个坏习惯,因为:

  1. class 的每个实例都会有一个具有相同值的此变量的副本,因为它打算用作全局常量,这是一种内存浪费。
  2. 静态访问常量是不可能的,所以MyClass.ERROR_CODE不会编译,如果你只需要这个值,你总是需要一个实例,例如new MyClass().ERROR_CODE

#2 静态变量

静态变量在某些情况下很有用,例如单例模式或 class 相关的缓存,或者当你想在相同 class

的所有实例之间共享一些公共数据时

#3 是

也许您的 class 还没有做到这一点,但是 class 是一个对象,由 classloader 管理。 classloader 加载 class 并确保只有一个 class 对象。 class 对象是静态变量和方法所在的地方。

对于#1,静态意味着有一个变量属于class。没有 static 的声明意味着它是一个实例变量,并且您为 class 创建的每个实例都有自己的变量。对于常量,将您的变量设置为 static final,这样就只有一个。

Final 表示值不变。如果变量是原始变量,则不能重新分配值。如果变量是引用类型,则不能更改变量指向的内容。如果指向的对象本身是可变的,则 final 不会更改它。

对于2,静态变量属于class,你的一个静态方法可以改变变量中的内容,其他方法可以看到变化。全局可变状态令人困惑,而且您正在将 OO 良好实践抛在脑后,进入肮脏的黑客领域,因此在使用此功能时非常谨慎是个好主意。

#3:来吧,你可以在大约 10 秒内亲自尝试一下。无论哪种方式都有效。 google style guide 建议“static final”。

1:static 不是 需要的 只要常量只能从实例中访问(或使用实例)。但是要在没有实例的情况下访问它,它必须是 static。更重要的是,恕我直言,它应该是一个 class 变量,因为拥有一个常量(独立于实例)的实例变量是没有意义的 - 另请参见下一点。

2:你所描述的是功能 - 某种相关的数据设计,数据模型,static 表示 class 成员(字段,方法)与实例对比成员 - OO 设计的重要组成部分

3:顺序不重要...但是,Java Language Specification 建议:

MethodModifier: (one of) Annotation public protected private abstract static final synchronized native strictfp
...
If two or more (distinct) method modifiers appear in a method declaration, it is customary, though not required, that they appear in the order consistent with that shown above in the production for MethodModifier.