私人最终静态属性vs私人最终属性
在Java中,有什么区别:
private final static int NUMBER = 10;
和
private final int NUMBER = 10;
两者都是private
和final
,区别在于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.instanceVariable
和x.instanceVariable
是分开的,因为x
和y
指的是不同的对象。
你可以通过引用来引用静态成员,尽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.
一个static
variables在应用程序的整个生命周期中保留在内存中,并在类加载期间被初始化。 每当你构造一个new
对象时,一个非static
variables被初始化。 通常使用更好:
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."); } }