将属性值名称存储为字符串常量 - 性能和内存使用情况?

eol*_*old 3 java string performance properties constants

我使用了大约1000个与特定java.util.Properties相关联的属性,这些属性由文件支持.该文件的主要原因是更改它们而不重新编译程序,并允许用户根据自己的喜好调整它们.某些属性仅在代码中的一个位置使用,但有些属性在不同的代码段甚至不同的类中多次使用.

我最近习惯于声明所有那些用作String常量的属性,通常是在一个单独的界面中,如下所示:

public interface AnimalConstants {
  public static final String WEIGHT_PROPERTY = "weight";
  public static final String RUNNING_SPEED_PROPERTY = "speedInKph";
  public static final String HOURS_OF_SLEEP_A_DAY_PROPERTY = "sleepHrs";
  ...
}
Run Code Online (Sandbox Code Playgroud)

当一个类需要访问一些动物属性时,我只是实现了这个接口,我可以访问所有声明的属性常量.当我需要一个特定的属性时,我只使用相应的常量,而不考虑它的确切名称(因为经常使用缩写),更重要的是,这种方式消除了错误输入属性名称的风险.另一个优点是,如果我稍后选择重命名属性以使配置这些属性的高级用户更清楚),我只需要在声明该属性常量的接口中更改该名称(当然还有属性文件) ),所以不需要"搜索和替换"整个项目.最后,我可以轻松检查财产是否被使用; 我只是评论它,编译代码,看看是否有错误.

然而,尽管有这些优点,我很好奇这种方法的缺点是什么.我最感兴趣的是以下内容:

  • 这个方法(1000个字符串常量)对字符串池有什么影响?或者,当我访问这些常量时,它们是按需创建的?这是否会阻止其他字符串在字符串池中缓存?
  • 与使用硬编码字符串常量的方法相比,这种方法的性能成本是多少,是否相同(忽略访问字段的成本)?字符串池的行为是相似还是有很大不同?
  • 这种方法的平均内存增加是多少,所有那些字符串常量一直保存在内存中?

任何好的评论/观察都是受欢迎的.

YoK*_*YoK 7

在类加载期间,在初始化阶段初始化静态字段.

但是,如果将基本类型或String定义为常量并且在编译时已知该值,则编译器会将代码中的常量名称替换为其值.这称为编译时常量.如果外部世界中常量的值发生变化(例如,如果立法实际上pi应该是3.975),则需要重新编译使用此常量来获取当前值的任何类.这是当创建唯一字符串的字符串文字时,它被定义为常量的值.

但它类似于从Properties对象中的资源加载常量(为其编写代码).常量肯定会消耗内存.字符串池行为不会改变.

关于设计方法的一些想法:

将所有配置常量放在一个类中非常容易,然后在整个应用程序中引用它们.要更改静态配置常量,请修改源并重新编译.如果在将来的某个时刻,您的程序需要维护多个配置,或者在处理不同文件时在配置之间交替,或者甚至运行具有一个配置的一个线程和另一个具有不同配置的线程,该怎么办?您将无法使用该技术.因此,对于更好的设计,您可以存储永远不会在类定义中作为静态常量更改的常量.只要在内存中加载Class,就会加载它们.在我之前描述的其他情况下(资源加载),您可以将它们保存在各种属性文件中,这些文件可以在JAVA Properties对象中加载.


Suj*_*jee 5

1)这种方法(1000字符串常量)对字符串池有什么影响?

将属性名称声明为String常量是正确的决定.但是"字符串文字池"中没有任何变化.当存在相同文字的多个实例时,它们都只是链接到文字池中的相同项目(不提供String构造函数).

2)当我访问这些常量时,它们是按需创建的吗?

在类加载期间,字符串文字被添加到"字符串文字池"中.

3)这是否会阻止其他字符串在字符串池中缓存?

没有.

4)与使用硬编码字符串常量的方法相比,这种方法的性能成本是多少,是否相同(忽略访问字段的成本)?字符串池的行为是相似还是有很大不同?

这是相同的.

5)这种方法的平均内存增加是多少,所有那些字符串常量一直保存在内存中?

我已经回答了.:)

补充说明

a)常量接口是Java反模式.请避免它.

b)您必须阅读此Javaranch文章.