【问题标题】:Define constant "Value" for enum string values为枚举字符串值定义常量“值”
【发布时间】:2019-08-29 07:20:37
【问题描述】:

对于如下定义的枚举

public enum Cars {

    SWIFT("Maruti"),
    DZIRE("Maruti"), 
    CIAZ("Maruti"), 
    I10("Hyundai"), 
    CRETA("Hyundai");

    String company;
    Cars(String company){
        this.company = company;
    }   
}

有声纳错误

Define a constant instead of duplicating this literal "Maruti" 3 times.

如果我们定义静态字符串,编译失败

Cannot reference a field before it is defined

解决方案 1:

public enum Cars {

    SWIFT(CarsString.MARUTI.companyName),DZIRE("Maruti"), I10("Hyundai"), CRETA("Hyundai");

    static String MARUTI = "Maruti";
    String company;
    Cars(String company){
        this.company = company;
    }

    enum CarsString {
        MARUTI("maruti"),
        HYUNDAI("Hyundai");
        String companyName;
        CarsString(String companyName){
            this.companyName = companyName;
        }
    }
}

解决方案 2:

不确定这是否是我们的做法。当 Cars.MARUTI 没有引用它时,它会出错Cannot reference a field before it is defined

public enum Cars {

    SWIFT(Cars.MARUTI),DZIRE(Cars.MARUTI), I10("Hyundai"), CRETA("Hyundai");

    public static final String MARUTI = "Maruti";
    String company;
    Cars(String company){
        this.company = company;
    }
 }

我有 10 个处于相似状态的枚举,而上述解决方案 1 并没有给我太多鼓励。方案2解决了目的,

但是我们为什么要直接引用Cars.MARUTI 而不是MARUTI?这是限制吗?

我们如何在枚举中引用一个常量?

【问题讨论】:

  • @AmitBera but why should we refer by Cars.MARUTI and not MARUTI directly ? is that a limitation ? 这是我不知道的附加问题
  • 请参考我的回答以获得解释。谢谢。

标签: java enums sonarqube


【解决方案1】:

如何在自己的 Enum 中定义公司?例如:

public enum Car {
    SWIFT(Company.MARUTI),
    DZIRE(Company.MARUTI),
    CIAZ(Company.MARUTI),
    I10(Company.HYUNDAI),
    CRETA(Company.HYUNDAI);

    Company company;

    Cars(Company company) {
        this.company = company;
    }
}

public enum Company {
    HYUNDAI("Hyundai"),
    MARUTI("Maruti");

    String name;

    Company(String name) {
        this.name = name;
    }
}

更新:根据@Basil Bourque 的评论改进了命名约定,谢谢!

【讨论】:

  • 好答案。几点建议。枚举应命名为单数,Car 而不是Cars。按照惯例,枚举的每个命名元素都应全部大写,即MARUTI("Maruti")。提示:至少在美国,我们通常使用术语“制造商”和“型号”来表示汽车制造商,而特定的类型是汽车。这些可能会产生更好的枚举名称。
  • 如果您看到解决方案1,那就是问题中提到的内容。这不是关于如何定义枚举,而是我们如何避免枚举常量值中的字符串文字和现有应用程序的可行事物。谢谢
【解决方案2】:

您需要知道枚举在内部是如何工作的。如果您查看枚举的字节码,您将得到答案。

 6: iconst_0
   7: ldc           #19                 // String Maruti
   9: invokespecial #21                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
  12: putstatic     #25                 // Field SWIFT:Labc/Cars;
  15: new           #1                  // class abc/Cars
  18: dup
  19: ldc           #27                 // String DZIRE
  21: iconst_1
  22: ldc           #19                 // String Maruti
  24: invokespecial #21                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
  27: putstatic     #28                 // Field DZIRE:Labc/Cars;
  30: new           #1                  // class abc/Cars
  33: dup
  34: ldc           #30                 // String CIAZ
  36: iconst_2:

从上面的byte code(由 Cars 枚举生成),我们可以有一个类似于Cars enum 的类

class Foo {
    public static Cars SWIFT = new Cars("Maruti");
    public static Cars DZIRE = new Cars("Maruti");
    public static Cars CIAZ = new Cars("Maruti");
}

现在,如果您将代码更改为:

class Cars {

    public static Cars SWIFT = new Cars(MARUTI); //statement-1
    public static Cars DZIRE = new Cars(MARUTI); //statement-2
    public static Cars CIAZ = new Cars(MARUTI); //statement-3

    public static String MARUTI = "Maruti"; // statement-4


    private String name;

    public Cars(String name) {
        this.name = name;
    }
}

它会给你同样的错误信息,因为你使用的是variable before it is defined。如果我们在statement-1 之前向上移动statement-4,它将起作用。但它是only possible in class but enum does not allow you as the first 声明。所以在你的情况下,你可以像这样解决:

enum Cars {

    SWIFT(Constants.MARUTI), DZIRE(Constants.MARUTI), I10("Hyundai"), CRETA("Hyundai");

    String company;

    Cars(String company) {
        this.company = company;
    }

    private static class Constants {

        public static String MARUTI = "Maruti";
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-25
    • 2021-12-23
    • 1970-01-01
    • 2023-03-04
    • 2011-03-27
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多