假设我有一个简单的类:
public class Car {
public static final int TYPE_SUV = 1;
public static final int TYPE_TRUCK = 2;
public String name;
public int carType;
}
现在,如果我有一个这些元素的集合,我知道我正在为集合中的每个元素分配一个String
和一个int
,但我是否也多次存储静态int
?这个精心设计的示例类代表了我几年前写的Java,在我了解到像这样的幻数更好地与enum
一起使用之前,CCD_4是在一个单独的类中定义的,但我一直想知道这段代码的副作用是什么
来自1.7 JLS:
如果一个字段被声明为静态,那么无论最终可能创建多少个类实例(可能为零),该字段都只存在一个化身。静态字段,有时称为类变量,在初始化类时体现出来(§12.4)
未声明为静态的字段(有时称为非静态字段)称为实例变量。每当创建一个类的新实例时(§12.5),就会为该类或其任何超类中声明的每个实例变量创建一个与该实例相关的新变量。
需要注意的关键点是,内存是在每个类(而不是实例)的基础上消耗的,无论您有多少实例(1000个或没有实例)。
就其价值而言:name
和carType
实例变量仅在创建实例时分配。更重要的是,在java7之前,具有相同值的String
s可以被插入到String管理的内存中(在PermGen中),该内存在任何使用的地方都被引用的单个String实例中进行维护。当java 1.7被移到主堆时,这种情况发生了变化,并且似乎在java 8 中再次发生变化(?)
任何地方都不会存储副本,而是创建了对内存中(堆上)同一位置的多个引用。
static
变量与不带Object的类相关。因此,您创建了多少个Object
,但static
变量将在内存中间隔一次,并且所有Static context
都在类加载时加载,因此在不创建Object
的情况下,您也可以在class
名称的帮助下访问static
变量。
不维护static
的多个副本。所有的CCD_ 16都具有CCD_。如果他们有,那么你必须access
他们using object
,但这不是我们对static
所做的。
存储引用的惩罚=创建类的惩罚。