在Java中,有什么区别:

private final static int NUMBER = 10;

and

private final int NUMBER = 10;

两者都是私有的和final的,不同的是静态属性。

更好的是什么?,为什么?


当前回答

Final:一旦Final变量被赋值,它总是包含相同的值。 无论变量是否是静态的 static:对于内存中一次初始化的所有实例,它将只有一个变量

其他回答

对于final,可以在初始化时在运行时分配不同的值。 例如

class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

因此,每个实例都有不同的字段a值。

对于静态final,所有实例共享相同的值,并且在第一次初始化后不能更改。

class TestStatic{
      public static final int a = 0;
}

TestStatic t1  = new TestStatic();
t1.a = 10; // ERROR, CAN'T BE ALTERED AFTER THE FIRST 
TestStatic t2  = new TestStatic();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.

非常少,而且是静态的

因为它们都是常数,所以区别不大。对于大多数类数据对象,静态意味着与类本身相关联的东西,无论用new创建了多少个对象,都只有一个副本。

因为它是一个常量,所以它实际上可能不会存储在类中或实例中,但是编译器仍然不会让你从静态方法访问实例对象,即使它知道它们会是什么。如果您不使反射API成为静态的,那么它的存在也可能需要一些无意义的工作。

以下是我的观点:

final           String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
final   static  String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";

例子:

package test;

public class Test {

    final long OBJECT_ID = new Random().nextLong();
    final static long CLASSS_ID = new Random().nextLong();

    public static void main(String[] args) {
        Test[] test = new Test[5];
        for (int i = 0; i < test.length; i++){
            test[i] = new Test();
            System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value
            System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different
        }
    }
}

关键是变量和函数可以返回不同的值。因此,最终变量可以被赋予不同的值。

读了答案后,我发现没有真正的测试能真正抓住重点。以下是我的观点:

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {


        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " + 
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " + 
                ObjectUtils.identityToString(valueObjectStatic));
    }


    public static void main(final String args[]) {


        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

第一个对象的结果:

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@6c22c95b
final static file address java.io.File@5fd1acd3

第二个对象的结果:

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@3ea981ca
final static file address java.io.File@5fd1acd3

结论:

正如我认为java使原始类型和其他类型之间的区别。Java中的基本类型总是“缓存”的,对于字符串字面量也是如此(不是新的String对象),所以静态和非静态成员没有区别。

然而,如果非静态成员不是基元类型的实例,则存在内存复制。

将valueStatic的值更改为10甚至可以更进一步,因为Java将为两个int变量提供相同的地址。

根据Jon的回答,如果你使用静态韵母,它将表现为一种“定义”。一旦你编译了使用它的类,它将在编译后的.class文件中被烧毁。 在这里查看我的帖子。

对于你的主要目标:如果你没有在类的不同实例中使用不同的NUMBER,我建议使用final和static。 (您只需要记住,在不考虑像我的案例研究所描述的那样可能出现的问题的情况下,不要复制已编译的类文件。大多数情况下不会发生这种情况,别担心:))

为了向你展示如何在实例中使用不同的值,检查下面的代码:

public class JustFinalAttr {
  public final int Number;

  public JustFinalAttr(int a){
    Number=a;
  }
}

...System.out.println(new JustFinalAttr(4).Number);