我不确定我是否正确,但SonarLint给了我无数关于重复使用某些字符串的警告。
因此,我创建了一个纯粹用于模块中的字符串的常量文件,该文件已在项目中的所有其他模块中访问。
我的想法是,如果我们不断被警告这一点。它可能多次创建这些字符串中的每一个并暂时增加内存。 (这是一个Web应用程序,生成JSON和XML,其中包含许多经常重复的术语,例如"身份"或"社区")
我想知道的问题是,我的IDE(IntelliJ)似乎只是不断添加以下行:
import static com.*****.*****.resources.Constants.*
而不是:
import static com.*****.*****.resources.Constants.PARAM_NAME_HASEMAIL;
import static com.*****.*****.resources.Constants.PARAM_NAME_HASSMS;
import static com.*****.*****.resources.Constants.PARAM_NAME_CMD;
请记住,该文件目前很小,可能有大约 100 个常量,但这个数字最终将达到 250 个。
首先我的问题是,哪个导入更有效,只需导入文件,导入每个所需的常量,或者没那么重要(文件中的最大值肯定是 250 个常量)
我的第二个问题是,这值得付出努力(简单但繁重的工作)? 一个例子是:
data.has(PARAM_NAME_OPTIN)
data.remove(PARAM_NAME_OPTIN);
data.put(PARAM_NAME_OPTINTYPE, Coupon.OPTIN_MODE_SINGLE_OPTIN);
以上可能是不同文件中的 3 或 4 个位置。 这两个常量的定义是:
public static final String PARAM_NAME_OPTIN = "optin";
public static final String PARAM_NAME_OPTINTYPE = "optInType";
最严重的罪犯在下面。在每一个方法中,从前端调用后端(遵循浏览器中的ajax请求):
json.put(PARAM_NAME_CMD, "Coupon.doSearchCouponEntriesByCoupon");
json.put(PARAM_NAME_APPID, PARAM_NAME_CAMPAIGN);
json.put(PARAM_NAME_COMMUNITYID, session.getAttribute(PARAM_NAME_COMMUNITYID));
json.put(PARAM_NAME_IDENTITYID, session.getAttribute(PARAM_NAME_IDENTITYID));
同样,定义是:
public static final String PARAM_NAME_APPID = "applicationId";
public static final String PARAM_NAME_CMD = "command";
public static final String PARAM_NAME_CAMPAIGN = "*****campaign";
public static final String PARAM_NAME_COMMUNITYID = "communityId";
public static final String PARAM_NAME_IDENTITYID = "identityId";
我为软件包名称加了星标,试图掩盖公司。即使这并没有真正共享任何IP或机密,安全总比抱歉好。
感谢您提供的任何反馈(好或坏)。
附加信息:我正在为每个使用的文件手动导入其中一个文件,当前对这些常量有 22 个导入。 我想如果数字达到这样的高度,那么也许我应该切换到 *?还是它仍然有记忆影响?
的想法是,如果我们不断被警告这一点。它可能多次创建这些字符串中的每一个并暂时增加内存。(这是一个Web应用程序,生成JSON和XML,其中包含许多经常重复的术语,例如"identityId"或"communityId")
这实际上是错误的。 在运行时,所有字符串文本都由类装入器驻留。 因此,如果您在许多不同的类中有 20 个"identityId"
示例,则在运行时将只有一个表示文本所有副本的String
对象。 (这不是实现细节。 JLS 保证此行为。
SonarLint 警告的真正原因是,拥有同一字符串文字的多个副本可能会导致维护问题。 如果你想"identityId"
更改为"identityID"
,你有 20 个单独的地方可以更改它......IDE不会提供很多帮助。
首先我的问题是,哪个导入更有效,只需导入文件,导入每个所需的常量,或者没那么重要
它对运行时性能的影响为零,对编译速度的影响很可能微不足道。
不同风格的import
最显着的影响是对源代码的可读性的影响,这在很大程度上是一个意见问题。
我的第二个问题是,这值得付出努力吗?
这绝对是一个意见问题....在您介绍的示例中。
但是,如果字符串是供用户阅读的消息,则可能需要对其进行国际化。 如果是这种情况,那么您最好将字符串存储在(例如)属性文件中......并根据用户的首选语言使用不同的文件。
最后,假设您决定使用 String 常量(这是一个好主意),我不建议将它们全部放入一个大的"常量"类中。 根据它们的用途在普通类和接口中定义它们。
重复使用相同的文字字符串不会产生内存开销,因为 Java 源代码中的所有文字字符串都被扣留。SonarLint 警告您不是因为内存效率低下,而是因为存在错误和可读性降低的风险。
使用整个类的静态导入提出的解决方案的问题在于,当您稍后阅读使用常量的源代码时,您将不知道常量来自哪里。这就是为什么它通常比"静态导入"命名字段更受欢迎。但是,如果您有 250 个这样的常量,您可能不希望向文件添加 250 个静态导入行。
不要将常量命名为PARAM_NAME_APPID
等,而是将它们放在一个名为 ParamNames 的类中。然后你"静态导入"类名,这样你就可以看到它来自哪里,并且常量有不言自明的名称:
static import package.name.ParamNames;
....
xxx = ParamNames.APP_ID;
将Constants
类重构为属性文件。
然后它包含像这样的常量
PARAM_NAME_APPID=applicationId
您可以使用以下方法加载它
Properties constants = new Properties();
try (FileReader reader = new FileReader("constants.properties")) {
constants.load(reader);
}