在类中声明final
变量(常量)时,例如:
private static final int MyVar = 255;
如果我有100,000个声明这个类的实例,那么这需要多少内存?
它会将变量链接到类,因此具有1 * MyVar内存使用量(忽略内部指针),还是会链接到此变量的实例并创建此变量的100,000 * MyVar副本?
难以置信的快速反应!共识似乎是,如果变量既是静态的又是最终的,那么它将需要1 * MyVar。谢谢大家!
答案 0 :(得分:19)
final
关键字与使用的内存量无关,因为它只表示您无法更改变量的值。
但是,由于变量声明为static
,因此只有一个这样的变量属于该类而不属于特定实例。
取自here:
如果一个字段被声明为
static
,那么无论该类最终会创建多少个实例(可能为零),都只存在该字段的一个化身。初始化类时,静态字段(有时称为类变量)将被体现。未声明为静态的字段(有时称为非静态字段)称为实例变量。每当创建一个新的类实例时,就会为该类或其任何超类中声明的每个实例变量创建一个与该实例关联的新变量。
答案 1 :(得分:12)
只有1 * MyVar内存使用,因为它被声明为 static
。
答案 2 :(得分:4)
静态声明意味着它只有一个实例用于该类及其子类(除非它们覆盖MyVar)。
int是一个32位有符号2的补码整数原语,所以它需要4个字节来保存它,如果你的例子没有使用静态,你只需将它乘以你拥有的实例数(对于你的例子) 100,000个实例,即0.38兆字节 - 仅对于该字段,实际类的额外开销。)
字段上的最终修饰符意味着它不能被重新赋值给另一个值(而一类方法的最终修饰符意味着它不能被覆盖)。
答案 3 :(得分:3)
它是静态的,因此是类范围 - > 1。
编辑:实际上,它取决于类加载器。在一般情况下,您有一个类的副本,但如果您有多个类加载器/类存储库(可能在应用程序服务器等情况下),您最终可能会有更多。
答案 4 :(得分:2)
除了static
字段属于它们的类这一事实,因此每个类(和每个类加载器)只有一个static
变量的实例,因此理解{{1}很重要由编译时常量表达式初始化的变量被内联到使用它们的类中。
JLS §13.1 The Form of a Binary:
对作为常量变量的字段(第4.12.4节)的引用在编译时被解析为表示的常量值。在二进制文件的代码中不应该存在对这样的常量字段的引用(除了包含常量字段的类或接口,它将具有初始化它的代码),并且这样的常量字段必须总是看起来已经初始化;不得观察此类字段类型的默认初始值。
因此,实际上,属于其类的static final
变量的实例不是该变量的唯一值实例 - 该值的其他实例内联到类的常量池(或代码)中使用有问题的变量。
static final
实际上,这意味着如果更改类class Foo {
public static final String S = "Hello, world!";
}
class Bar {
public static void main(String[] args) {
// No real access to class Foo here
// String "Hello, world!" is inlined into the constant pool of class Bar
String s = Foo.S;
System.out.println(s);
}
}
中Foo.S
的值,但不重新编译类Foo
,则类Bar
将打印旧值Bar
。
答案 5 :(得分:1)
静态表示您只有一次生命
最终只是意味着您无法重新分配该值。
答案 6 :(得分:1)
这里的关键部分是你将变量声明为static
,因为静态变量在类的所有实例中都是 shared ,因此只需要与变量的一个实例一样多的空间。声明变量final
使其在声明或构造函数之外不可变。
答案 7 :(得分:1)
final
使得内存使用量为1*instances
。
但是,static
只是1
。
答案 8 :(得分:1)
关键字“final”可以帮助您声明具有特定内存量的常量,其中关键字“static”作为其前缀将给出此常量的单个实例,即消耗的内存量。 。!!!
答案 9 :(得分:0)
它是静态的,因此只会创建一个实例,因此需要多个字节来保存一个int原语
答案 10 :(得分:0)
每个班级都有一个实例。如果您已经多次加载类(在不同的类加载器中),则每个加载它的类加载器将加载一次。
BTW:这些天记忆力惊人。即使每个实例都有一个副本,您提出问题所花费的时间比您节省的内存更有价值。为了清晰而不是表现,你应该static final
。更清晰的代码更易于维护,并且通常也更有效。
答案 11 :(得分:0)
静态表示每个类一个实例,静态变量只创建一次,并且可以在不同对象之间共享。
最终变量,值一旦初始化就无法更改。最终的静态变量用于创建常量(不可变)并直接引用而不使用对象。