对于Singleton类,将String常量(在成员函数中内部使用)保留为private static final
或private final
是个好主意吗?
我想了解更多关于长时间运行的应用程序和其他应用程序的类内存占用的差异。
注意:我知道static
和final
如何影响一个变量。我的问题是针对类中用作private
的常量的。更具体地说,关于那里的生活。即使在内存中没有该类的对象。
字符串常量通常在使用它的代码有效期内有效。虽然在理论上,没有被变量引用的String常量可以在下次使用时释放并重新创建,但当前JVM不会发生这种情况。
尽管如此,保持引用的字段还是有一点开销,不仅是对象引用的大小,还有相关的元数据,这是可以避免的。只需将常量放在一个专用的holder类中:
public class Singleton {
private static final class Constants {
static final String CONSTANT_1 = "Foo";
static final String CONSTANT_2 = "Bar";
static final String CONSTANT_3 = "Baz";
static final String CONSTANT_4 = "etc";
private Constants() { throw new AssertionError(); }
}
// …
// Use the constants either via Constants.CONSTANT_1, etc.
// or using import static Singleton.Constants.*; and
// unqualified names ala CONSTANT_1, CONSTANT_2, etc.
// …
}
该类不需要是嵌套类,但Constants
被设计为嵌套类,按预期为private
到Singleton
。由于我们谈论的是常量,它们的使用并不意味着字段访问,相反,将使用常量值。换言之,由于嵌套类Constants
从未在运行时实际使用过,因此它永远不会被加载,因此字段既不占用内存,也不在堆中,也不占用元空间中。
剩下的,是代码实际引用的常数值。如前所述,如果代码没有运行更长的时间(只要没有其他代码或变量引用相同的常量),甚至在理论上也有收集字符串实例的可能性,但当前JVM没有使用这种可能性。在代码可访问时收集String实例也意味着有必要将原始内容(例如类文件形式)保留在手边。
需要强调的是,引用常量的代码将是相同的,无论常量是final
变量,如static
或Singleton
中的实例字段、另一个holder类中的static
字段,甚至是局部变量。这些变体只在是否存在或存在哪种类型的附加变量方面有所不同,这些变量指的是相同的常数。
它们之间没有太大区别,只是private static final String
在程序初始化时初始化,private final String
在创建Singletons实例时初始化。
static
String的唯一优点是,您也可以在静态方法中使用它(如果需要的话)
此外,这两个变量都没有性能问题,因为只要程序正在运行,这两种变量就不会被垃圾收集。