Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define constant "Value" for enum string values

For the enum defined as below

public enum Cars {

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

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

There is Sonar error

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

If we define static string, it fails to compile

Cannot reference a field before it is defined

Solution 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;
        }
    }
}

Solution 2:

Not sure if this is the way we do it. When it is not referenced by Cars.MARUTI, it errors out 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;
    }
 }

I have 10 enums in similar state and the above solution 1 didn't much encourage me. Solution 2 solves the purpose,

but why should we refer by Cars.MARUTI and not MARUTI directly? is that a limitation ?

How could we refer a constant value in enum ?

like image 462
Vinay Veluri Avatar asked Aug 29 '19 07:08

Vinay Veluri


People also ask

How do you declare a constant in an enum?

To create an enum, use the enum keyword (instead of class or interface), and separate the constants with a comma. values() method can be used to return all values present inside enum.

Can enum have string values?

The enum can be of any numeric data type such as byte, sbyte, short, ushort, int, uint, long, or ulong. However, an enum cannot be a string type.

Can enum have constants?

An enum type is a special data type that enables for a variable to be a set of predefined constants.

Can we define string in enum?

We can't define enumeration as string type. The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.


2 Answers

What about defining the company in its own Enum? For example:

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;
    }
}

Update: improved naming conventions according to comment of @Basil Bourque, thx!

like image 122
Mark Schäfer Avatar answered Oct 19 '22 14:10

Mark Schäfer


You need to know how enum works internally. If you look at the byte code of your enum you will have the answer.

 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:

From the above byte code (which was generated from Cars enum), we can have a class which will be similar to the 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");
}

Now if you change the code to :

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;
    }
}

It will give you the same error message because you are using the variable before it is defined. If we move up the statement-4 before statement-1 it will work. But it is only possible in class but enum does not allow you as the first statement.So in your case you can solve like :

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";
    }
}
like image 23
Amit Bera Avatar answered Oct 19 '22 13:10

Amit Bera