私有final静态属性vs私有final属性

在Java中,有什么区别:

private final static int NUMBER = 10;

而且

private final int NUMBER = 10;

它们都是privatefinal,区别在于static属性。

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

380355 次浏览

static变量在应用程序的整个生命周期中都保留在内存中,并在类加载期间初始化。每次构造new对象时,都会初始化一个非-static变量。通常更好的方法是:

private static final int NUMBER = 10;

为什么?这减少了每个实例的内存占用。它可能也有利于缓存命中。这是有意义的:static应该用于在某个类型(a.k.a bc1)的所有实例(也就是对象)之间共享的东西。

通常,static表示“与类型本身相关联,而不是与该类型的实例相关联。”

这意味着您可以在不创建类型实例的情况下引用静态变量,并且引用该变量的任何代码都引用完全相同的数据。将其与实例变量进行比较:在这种情况下,类的每个实例都有一个独立的变量版本。例如:

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

y.instanceVariablex.instanceVariable是分开的,因为xy引用不同的对象。

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

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

然后输出20个变量——只有一个变量,而不是每个实例一个变量。这样写会更清楚:

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

这使得这种行为更加明显。现代ide通常建议将第二个清单改为第三个清单。

没有理由像下面这样使用内联声明初始化值,因为每个实例都有自己的NUMBER,但总是具有相同的值(不可变并使用文字初始化)。这与所有实例只有一个final static变量是一样的。

private final int NUMBER = 10;

因此,如果它不能更改,就没有必要为每个实例提供一个副本。

但是,如果在这样的构造函数中初始化是有意义的:

// No initialization when is declared
private final int number;


public MyClass(int n) {
// The variable can be assigned in the constructor, but then
// not modified later.
number = n;
}

现在,对于MyClass的每个实例,我们都可以有一个不同但不可变的number值。

静态意味着“与类相关联”;没有它,变量与类的每个实例相关联。如果它是静态的,这意味着内存中只有一个;如果没有,您将为创建的每个实例创建一个。静态意味着只要类被加载,变量就会保留在内存中;如果没有它,当变量的实例被回收时,变量就会被回收。

非常少,而且是静态的

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

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

正如Jon已经说过的,静态变量,也称为类变量,是跨类实例存在的变量。

我找到了一个在这里的例子:

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

程序输出如下:

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

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

静态成员是所有类实例和类本身的相同成员 非静态是每个实例(对象)的一个,所以在你的具体情况中,如果你在中放置static.

如果你将这个变量标记为static,那么你将需要静态方法来再次访问这些值,如果你已经考虑只在静态方法中使用这些变量,这将是有用的。如果是这样,那么这个就是最好的了。

但是,您现在可以将变量设为公共,因为没有人可以像“System”那样修改它。Out”,这取决于你的意图和你想要达到的目标。

从我所做的测试来看,静态最终变量与最终(非静态)变量是不一样的!最终(非静态)变量可以因对象而异!!但前提是在构造函数内部进行初始化!(如果它没有从构造函数初始化,那么它只是浪费内存,因为它为每个创建的不能更改的对象创建最终变量。)

例如:

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 静态Final: 5

关于对象:A@530daa 最后:21 静态Final: 5

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

假设类永远不会有多个实例,那么哪个实例占用更多内存:

私有静态最终int ID = 250; 或 private final int ID = 250;

我已经理解,静态将引用类类型,在内存中只有一个副本,而非静态将在每个实例变量的新内存位置。但是在内部,如果我们只是比较同一个类的1个实例(即不会创建多个实例),那么在1个静态final变量所使用的空间方面是否有任何开销?

对于最后,可以在初始化时在运行时分配不同的值。 例如< / p >
class Test{
public final int a;
}


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

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

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

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.

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

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变量提供相同的地址。

因为类中的变量在同一个命令中被声明为final和初始化, 绝对没有理由不将其声明为静态,因为无论实例如何,它都具有相同的值。因此,所有实例都可以为一个值共享相同的内存地址,这样就不需要为每个实例创建一个新变量,并通过共享一个公共地址来节省内存,从而节省处理时间
根据Jon的回答,如果你使用静态final,它将表现为一种“定义”。一旦你编译了使用它的类,它将在编译后的.class文件中被烧毁。 检查我的线程关于它在这里.

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

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

public class JustFinalAttr {
public final int Number;


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


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

这可能会有所帮助

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.");
}
}

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

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”,我们可以为类的每个实例(对象)分配变量,然而对于“static final int”,我们应该在类中分配一个变量(静态变量属于类)。

以下是我的观点:

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 TestClass {
private final static double NUMBER = Math.random();


public TestClass () {
System.out.println(NUMBER);
}
}

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

但是,当尝试下面的例子时:

public class TestClass {
private final double NUMBER = Math.random();


public TestClass () {
System.out.println(NUMBER);
}
}

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

我想不出在任何情况下,在不同的实例上有不同的常量值是真正有用的,但我希望这有助于指出静态韵母和非静态韵母之间有明显的区别。

私有静态final将被视为常量,并且只能在该类中访问该常量。因为包含了关键字static,所以该类的所有对象的值都是常量。

私有最终变量值将像每个对象的常量。

您可以参考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

这是另一个简单的例子来理解静态,静态final, final变量的用法。代码注释有适当的解释。

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);


}


}

如果你使用static,变量的值将在你所有的实例中是相同的,如果在一个实例中改变了,其他实例也会改变。

Final:一旦Final变量被赋值,它总是包含相同的值。 无论变量是否是静态的 static:对于在Memory

中初始化的所有实例,它将只有一个变量

"Static"关键字使类的变量属性而不是类的单个实例。该变量的一个副本将在该类的所有实例之间共享。静态变量状态中的任何变化都将在所有实例中反映出来。将final添加到static中,我们将得到一个在类加载时一次性初始化的变量,并且以后不能被类的任何实例更改。静态final变量需要在声明时初始化,否则会出现编译时错误。 就私有实例字段而言,它指的是类的对象/实例的属性/状态。类的每个实例/对象都有自己的实例变量副本。当实例变量被声明为final时,这意味着我们不能更改该实例的值。为此,我们需要在声明中或在构造函数中初始化最终变量。如果其中任何一个都没有执行,则会显示编译时错误。一旦初始化,如果你试图重新分配一个值,你会得到一个编译时错误。使用静态final变量,其中数据将在类的所有实例之间共享,并且您希望数据是只读的。如果您希望表示属于类的每个单独实例但一旦存储就不能更改的一些数据,则使用instance final变量。静态关键字和实例关键字的使用取决于您的设计需求以及该数据在域中表示的内容。如果数据是跨类实例使用的,则不需要为每个对象单独的副本/内存引用