代码之家  ›  专栏  ›  技术社区  ›  Jamie Reid

静态导入文件或静态导入单个项目

  •  1
  • Jamie Reid  · 技术社区  · 8 年前

    我不确定这一点是对还是错,但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个导入这些常量。 我想如果这个数字达到这样的高度,那么也许我应该换成*来代替?还是它仍然有记忆的暗示?

    3 回复  |  直到 8 年前
        1
  •  2
  •   Stephen C    8 年前

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

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

    Sonarint警告的真正原因是,具有相同字符串文字的多个副本可能会导致维护问题。如果你想改变 “标识ID” "identityID" ,您有20个单独的位置可以更改它。。。IDE也不会有什么帮助。

    首先,我的问题是,哪种导入更有效,只需导入文件,导入每个必需的常量,或者这并不重要

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

    不同风格的 import 主要取决于源代码的可读性,这在很大程度上是一个意见问题。

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

    那就是 肯定 意见问题。。。。在您介绍的示例中。

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

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

        2
  •  1
  •   DodgyCodeException    8 年前

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

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

    而不是命名常量 PARAM_NAME_APPID 等等,将它们放入一个名为ParamNames的类中。然后,您可以“静态导入”类名,以便查看其来源,并且常量具有自解释的名称:

    static import package.name.ParamNames;
    ....
    xxx = ParamNames.APP_ID;
    
        3
  •  -1
  •   daniu    8 年前

    重构 Constants 类转换为属性文件。

    然后它包含如下常量

    PARAM_NAME_APPID=applicationId
    

    你可以使用

    Properties constants = new Properties();
    try (FileReader reader = new FileReader("constants.properties")) {
        constants.load(reader);
    }
    
    推荐文章