1

我不确定我是对还是错,但 SonarLint 给了我无数关于重复使用某些字符串的警告。

结果,我为模块中的字符串创建了一个常量文件,该模块已在项目中的每个其他模块中访问。

我的想法是,如果我们不断被警告这一点。它可能会多次创建这些字符串中的每一个并暂时增加内存。(它是一个网络应用程序,生成带有许多经常重复的术语的 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 个导入。我想如果数字达到这样的高度,那么也许我应该改用*?还是它仍然有记忆影响?

4

3 回答 3

2

我的想法是,如果我们不断被警告这一点。它可能会多次创建这些字符串中的每一个并暂时增加内存。(它是一个 Web 应用程序,生成带有许多经常重复的术语的 JSON 和 XML,例如“identityId”或“communityId”)

这实际上是错误的。在运行时,所有字符串文字都由类加载器进行实习。因此,如果您"identityId"在许多不同的类中有 20 个示例,那么在运行时您将只有一个String对象代表文字的所有副本。(这不是实现细节。JLS 保证这种行为。)

SonarLint 警告的真正原因是拥有相同字符串文字的多个副本可能会导致维护问题。如果您想更改"identityId""identityID",则有 20 个不同的地方可以更改它……而且 IDE 不会有太大帮助。

首先我的问题是,哪个导入效率更高,只需导入文件,导入每个所需的常量,或者没那么重要

它对运行时性能的影响为零,对编译速度的影响很可能微不足道。

不同风格的最显着影响import是对源代码的可读性,这在很大程度上是一个见仁见智的问题。

我的第二个问题是,这值得努力吗?

绝对是一个意见问题....在您提供的示例中。

但是,如果字符串是供用户阅读的消息,那么您可能需要将它们国际化。如果是这种情况,那么您最好将字符串存储在(例如)属性文件中......并根据用户的首选语言使用不同的文件。

最后,假设您确实决定使用字符串常量(这是一个好主意),我不建议将它们全部放入一个大的“常量”类中。根据它们的用途,在普通的类和接口中定义它们。

于 2018-03-06T12:32:03.303 回答
1

重复使用相同的文字字符串不会产生内存开销,因为 Java 源代码中的所有文字字符串都是interned。SonarLint 警告您不是因为内存效率低下,而是因为存在错误风险和可读性降低。

您提出的使用整个类的静态导入的解决方案的问题在于,当您稍后阅读使用它们的源代码时,您将不知道这些常量的来源。这就是为什么通常首选“静态导入”命名字段的原因。但是如果你有 250 个这样的常量,你可能不想在你的文件中添加 250 个静态导入行。

与其命名常量PARAM_NAME_APPID等,不如将它们放在一个名为 ParamNames 的类中。然后你“静态导入”类名,这样你就可以看到它来自哪里,并且常量具有不言自明的名称:

static import package.name.ParamNames;
....
xxx = ParamNames.APP_ID;
于 2018-03-06T12:35:04.967 回答
-1

将类重构Constants为属性文件。

然后它包含这样的常量

PARAM_NAME_APPID=applicationId

你可以使用加载它

Properties constants = new Properties();
try (FileReader reader = new FileReader("constants.properties")) {
    constants.load(reader);
}
于 2018-03-06T12:12:28.887 回答