私人最终静态属性vs私人最终属性

在Java中,有什么区别:

private final static int NUMBER = 10; 

 private final int NUMBER = 10; 

两者都是privatefinal ,区别在于static属性。

什么更好? 为什么?

一般来说, static意味着“与types本身相关联,而不是types的一个实例 ”。

这意味着你可以引用一个静态variables,而不需要创build这个types的实例,任何引用这个variables的代码都指向完全相同的数据。 将它和一个实例variables进行比较:在这种情况下,每个类的实例都有一个独立版本的variables。 举个例子:

 Test x = new Test(); Test y = new Test(); x.instanceVariable = 10; y.instanceVariable = 20; System.out.println(x.instanceVariable); 

打印出10: y.instanceVariablex.instanceVariable是分开的,因为xy指的是不同的对象。

可以通过引用来引用静态成员,尽pipe这样做不是个好主意。 如果我们做到了:

 Test x = new Test(); Test y = new Test(); x.staticVariable = 10; y.staticVariable = 20; System.out.println(x.staticVariable); 

那么会打印出20个 – 只有一个variables,而不是每个实例。 这将会更清楚地写成:

 Test x = new Test(); Test y = new Test(); Test.staticVariable = 10; Test.staticVariable = 20; System.out.println(Test.staticVariable); 

这使得行为更加明显。 现代IDE通常会build议将第二个列表更改为第三个列表。

没有理由有这样的声明

 private final int NUMBER = 10; 

如果不能改变,每个实例都没有一个副本。

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

 Class Test{ public final int a; } Test t1 = new Test(); t1.a = 10; Test t2 = new Test(); t2.a = 20; //fixed 

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

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

 Class TestStatic{ public static final int a; } Test t1 = new Test(); t1.a = 10; Test t2 = new Test(); t1.a = 20; // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION. 

一个staticvariables在应用程序的整个生命周期中保留在内存中,并在类加载期间被初始化。 每当你构造一个new对象时,一个非staticvariables被初始化。 通常使用更好:

 private static final int NUMBER = 10; 

为什么? 这减less了每个实例的内存占用量。 这可能也有利于caching命中。 它只是有意义的: static应该被用于某个types(又名class )的所有实例(又名对象)共享的东西。

静态意味着“与class级相关”; 没有它,variables就与类的每个实例相关联。 如果它是静态的,那意味着你在内存中只有一个; 如果不是,则每个实例创build一个。 静态意味着只要类被加载,variables将保留在内存中; 没有它,variables可以被gc'd当它的实例。

阅读答案,我发现没有真正的考验真正到位。 这是我的2美分:

 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使原始和其他types的区别。 Java中的原始types总是“caching”,对于string文本(不是新的String对象)是一样的,所以静态和非静态成员之间没有区别。

但是,如果非静态成员不是基本types的实例,则存在内存重复。

由于Java将赋予两个intvariables相同的地址,因此将valueStatic的值更改为10会更进一步。

虽然其他答案似乎很明显,通常没有理由使用非静态常量,我找不到任何人指出有可能在其常量variables上具有不同值的各种实例。

考虑下面的例子:

 public class TestClass { private final static double NUMBER = Math.random(); public TestClass () { System.out.println(NUMBER); } } 

创buildTestClass的三个实例将打印三次相同的随机值,因为只有一个值被生成并存储到静态常量中。

但是,尝试下面的示例时:

 public class TestClass { private final double NUMBER = Math.random(); public TestClass () { System.out.println(NUMBER); } } 

现在创buildTestClass的三个实例将打印三个不同的随机值,因为每个实例都有自己的随机生成的常量值。

我想不出有什么情况下,在不同的情况下有不同的常量值是非常有用的,但我希望这有助于指出静态和非静态决赛之间有明显的区别。

很less,而且是静态的

没有太大的区别,因为它们都是常量。 对于大多数类数据对象,静态意味着与类本身相关联的东西,不pipe有多less对象是用新创build的,只有一个副本。

既然它是一个常量,它可能实际上并不存储在类或实例中,但编译器仍然不会让你从静态方法中访问实例对象,即使它知道它们是什么。 reflectionAPI的存在可能也需要一些毫无意义的工作,如果你不把它变成静态的。

正如Jon所说的那样,一个静态variables(也称为类variables)是一个跨类实例存在的variables。

我在这里find了一个例子:

 public class StaticVariable { static int noOfInstances; StaticVariable() { noOfInstances++; } public static void main(String[] args) { StaticVariable sv1 = new StaticVariable(); System.out.println("No. of instances for sv1 : " + sv1.noOfInstances); StaticVariable sv2 = new StaticVariable(); System.out.println("No. of instances for sv1 : " + sv1.noOfInstances); System.out.println("No. of instances for st2 : " + sv2.noOfInstances); StaticVariable sv3 = new StaticVariable(); System.out.println("No. of instances for sv1 : " + sv1.noOfInstances); System.out.println("No. of instances for sv2 : " + sv2.noOfInstances); System.out.println("No. of instances for sv3 : " + sv3.noOfInstances); } } 

该程序的输出如下:

正如我们在这个例子中看到的,每个对象都有自己的类variables副本。

 C:\java>java StaticVariable No. of instances for sv1 : 1 No. of instances for sv1 : 2 No. of instances for st2 : 2 No. of instances for sv1 : 3 No. of instances for sv2 : 3 No. of instances for sv3 : 3 

从我做的testing中,静态最终variables与最终(非静态)variables不一样! 最终(非静态)variables可能因对象而异! 但是,只有在构造函数中进行初始化! (如果它没有从构造函数初始化,那么它只是浪费内存,因为它为创build的每个无法更改的对象创build最终variables。)

例如:

 class A { final int f; static final int sf = 5; A(int num) { this.f = num; } void show() { System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf); } public static void main(String[] args) { A ob1 = new A(14); ob1.show(); A ob2 = new A(21); ob2.show(); } } 

屏幕上显示的是:

关于对象:A @ addbf1决赛:14静态决赛:5

关于对象:@ 530daa决赛:21静态决赛:5

匿名的第一年IT学生,希腊

除了Jon的回答,如果你使用static final,它将performance为一种“定义”。 一旦你编译了使用它的类,它将被编译的.class文件烧毁。 在这里检查我的线程。

为了您的主要目标:如果您不在class级的不同实例中使用NUMBER,我build议使用final和static。 (你只需要记住不要复制编译的类文件,而不考虑像我的案例研究所描述的可能的麻烦。大多数情况下,这不会发生,不要担心:))

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

 public class JustFinalAttr { public final int Number; public JustFinalAttr(int a){ Number=a; } } ...System.out.println(new JustFinalAttr(4).Number); 

这是我的两分钱:

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

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

由于一个类中的variables被声明为最终的并且在同一个命令中被初始化,所以绝对没有理由不将它声明为静态的,因为无论实例如何,它都具有相同的值。 因此,所有实例都可以共享相同的内存地址作为值,从而通过无需为每个实例创build新variables并通过共享1个公共地址来节省内存来节省处理时间。

私有静态最终将被视为常量,只有在这个类中可以访问常量。 由于包含关键字static,因此该类的所有对象的值都将保持不变。

私有的最终variables值将像每个对象不变。

您可以引用java.lang.String或查找下面的示例。

 public final class Foo { private final int i; private static final int j=20; public Foo(int val){ this.i=val; } public static void main(String[] args) { Foo foo1= new Foo(10); Foo foo2= new Foo(40); System.out.println(foo1.i); System.out.println(foo2.i); System.out.println(check.j); } } 

//输出:

 10 40 20 

静态的是所有类实例和类本身的相同成员。
非静态是每个实例(对象)的一个,所以在你的确如此的情况下 ,如果你放置静态的话,这会浪费内存。

如果你将这个variables标记为静态,那么你就会要求静态方法再次访问这些值,如果你已经想到只在静态方法中使用这些variables,这将是有用的。 如果是这样,那么这将是最好的。

但是现在你可以把这个variables作为public来使用,因为没有人可以象“System.out”那样修改它,这又取决于你的意图和你想达到的目的。

让我们说,如果这个类不会有一个以上的实例,那么哪一个需要更多的内存:

private static final int ID = 250; 或私人最终诠释ID = 250;

我明白,静态将指内存中只有一个副本的类types,非静态将在每个实例variables的新内存位置。 但是在内部,如果我们只是比较同一个类的一个实例(即多于一个的实例不会被创build),那么在1个静态最终variables使用的空间方面是否有任何开销?

静态variables属于类(这意味着所有的对象共享该variables)。 非静态variables属于每个对象。

 public class ExperimentFinal { private final int a; private static final int b = 999; public ExperimentFinal(int a) { super(); this.a = a; } public int getA() { return a; } public int getB() { return b; } public void print(int a, int b) { System.out.println("final int: " + a + " \nstatic final int: " + b); } public static void main(String[] args) { ExperimentFinal test = new ExperimentFinal(9); test.print(test.getA(), test.getB()); } } 

正如你可以看到上面的例子,对于“final int”,我们可以为类的每个实例(对象)分配我们的variables,但是对于“static final int”,我们应该在类中分配一个variables(静态variables属于类)。

只是另一个简单的例子来理解静态,静态最终,最终variables的用法。 代码评论有正确的解释。

 public class City { // base price that is always same for all objects[For all cities]. private static double iphone_base_price = 10000; // this is total price = iphone_base_price+iphone_diff; private double iphone_citi_price; // extra price added to iphone_base_price. It is constant per city. Every // city has its own difference defined, private final double iphone_diff; private String cityName = ""; // static final will be accessible everywhere within the class but cant be // changed once initialized. private static final String countryName = "India"; public City(String cityName, double iphone_diff) { super(); this.iphone_diff = iphone_diff; iphone_citi_price = iphone_base_price + iphone_diff; this.cityName = cityName; } /** * get phone price * * @return */ private double getPrice() { return iphone_citi_price; } /** * Get city name * * @return */ private String getCityName() { return cityName; } public static void main(String[] args) { // 300 is the City newyork = new City("Newyork", 300); System.out.println(newyork.getPrice() + " " + newyork.getCityName()); City california = new City("California", 800); System.out.println(california.getPrice() + " " + california.getCityName()); // We cant write below statement as a final variable can not be // reassigned // california.iphone_diff=1000; //************************ // base price is defined for a class and not per instances. // For any number of object creation, static variable's value would be the same // for all instances until and unless changed. // Also it is accessible anywhere inside a class. iphone_base_price = 9000; City delhi = new City("delhi", 400); System.out.println(delhi.getPrice() + " " + delhi.getCityName()); City moscow = new City("delhi", 500); System.out.println(moscow.getPrice() + " " + moscow.getCityName()); // Here countryName is accessible as it is static but we can not change it as it is final as well. //Something are meant to be accessible with no permission to modify it. //Try un-commenting below statements System.out.println(countryName); // countryName="INDIA"; // System.out.println(countryName); } } 

这可能有帮助

 public class LengthDemo { public static void main(String[] args) { Rectangle box = new Rectangle(); System.out.println("Sending the value 10.0 " + "to the setLength method."); box.setLength(10.0); System.out.println("Done."); } }