简体   繁体   中英

Enums as replacement of Constants in Java

I heard now a day that We should use Enums instead of Constants . Is it possible in all cases ? Whether enums are replacement of Constants ?

In Below Example I have Constants defined in Constants file and ConstantsTest uses them

public final class Constants {

private Constants(){

}
public static final String ACCOUNT="Account";
public static final String EVENT_ITEM ="EventItem";
public static final int MULTIPLIER_ONE = 1;
public static final int MULTIPLIER_NEGATIVE_ONE = -1;
public static final String BALANCE_AFTER_MODIFICATION = "BalanceAfterModification";
public static final String COMMA = ",";
public static final String DOTPSV =".psv";
public static final String NEW_LINE = "\n";
}


 // Test Class
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class ConstantsTest {
private static File rootDir = new File(".");    
public static void main(String[] args) throws IOException {

    Map<String,Integer> accountBalance = new HashMap<String, Integer>();
    accountBalance.put("123",55000);
    accountBalance.put("223",15000);
    writeToFile(Constants.ACCOUNT, accountBalance, true, 2000);
    // do operation 

 }

/**
 * 
 * @param fileType
 * @param inputData
 * @param add if true add balance  else substract the balance 
 * @return
 * @throws IOException
 */
 private static File writeToFile(String fileType , Map<String,Integer>accountBalance ,boolean add, int amount) throws IOException{
     File file = null; 
     FileWriter fw = null;
     try{
         if(Constants.ACCOUNT.equals(fileType)){
             file = new File(rootDir,Constants.ACCOUNT+Constants.DOTPSV);//creating a fileName using constants
             fw = new FileWriter(file);
             fw.write(Constants.ACCOUNT+Constants.COMMA+Constants.BALANCE_AFTER_MODIFICATION);//Writing Header in file using constant values
             updateBalance(accountBalance, add, amount);
             for(String key:accountBalance.keySet()){
                 fw.write(Constants.NEW_LINE);
                 fw.write(key+Constants.COMMA+accountBalance.get(key));
             }
         }
         else if(Constants.EVENT_ITEM.equals(fileType))
         {
             // write to EventItem.psv
         }
     } finally{
         if (null!=fw){
             fw.close();
         }
     }

     System.out.println("File created successfully");
     return file;

 }

private static void updateBalance(Map<String, Integer> accountBalance,
        boolean add, int amount) {
    for(String key:accountBalance.keySet()){
         int currentBal = accountBalance.get(key);
         if(add){
             accountBalance.put(key,currentBal+amount*Constants.MULTIPLIER_ONE); // do lot of calculations
         }else{
             accountBalance.put(key,currentBal+amount*Constants.MULTIPLIER_NEGATIVE_ONE);// do a lot of calculations
         }
     }
}

}

Please suggest in my sample example enums would be better or my current approach of using constants is good enough ?

In your particular case the using enums is classic solution.

First, let's re-write your Constants as an enum:

public enum Constants {
    ACCOUNT,
    EVENT_ITEM,
    ;

}

public enum Operation {
   MULTIPLIER_ONE {
        public int action(int value) {
            return value;
        }
   },
   MULTIPLIER_NEGATIVE_ONE {
        public int action(int value) {
            return value * (-1);
        }
   },
   ;
   private Operation(int coef) {
        this.coef = coef;
   }

   public abstract int action(int value);
}

Now instead of writing:

if(Constants.ACCOUNT.equals(fileType)){
} else if(....)

you can either use switch/case or even better define: define method (let's call it action() into the enum and call it from your code. See example in Operation enum above. In this case you code becomes trivial: no more if/else or switch statements. Everything is simple. Validation is done at compile time: you defined abstract method in enum you cannot add yet another element to enum without implementing this method for it. This does not happen when using if/else structures maintenance of which is a programmer's responsibility.

I know only one limitation of enums: using string contstants in annotations. There are a lot of annotations with string attributes. For example XmlElement(name="foo") . Even if you define enum

enum FooBar {
    foo, bar
}

you cannot use it in annotations:

@XmlElement(name=FooBar.foo) // is wrong because String type is required
@XmlElement(name=FooBar.foo.name()) // is wrong because annotations do not support method invocation 

In all other cases I prefer enum.

You should use enums this code

enum Constants {
  ACCOUNT,
  EVENT_ITEM ,
  COMMA ,
  DOTPSV ,
  BALANCE_AFTER_MODIFICATION ;

@Override
public String toString() {
  switch(this) {
    case ACCOUNT: return "Account";
    case EVENT_ITEM : return "EventItem";
    case COMMA : return ",";
    case DOTPSV : return ".psv";
    case BALANCE_AFTER_MODIFICATION : return "BalanceAfterModification";
    default: throw new IllegalArgumentException();
   }
 }
}

An Enum doesn't define a contract for the class using it, an interface does. A class which uses an Enum isn't of the type an Enum. A class which implements an Interface is effectively of the same type as the interface (the Interface is the parent.. and the reference could be changed). Considering these design issues. Tell me, is your approach correct?

Constants will be better for the example provided. Interface variables are public static final by default.

public static final String ACCOUNT="Account";

See Why are interface variables static and final by default?

You got enum wrong, it's not like you should create an enum instead of constant: an enum is a group of constants that are related, for example:

enum Days {
    SUNDAY, MONDAY, TUESDAY, ...
}

From the docs :

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

Only we can use Enums for the constant values which are in the single group. Let us suppose: Weeks, Months, Colours, Gender, Process states

It is not the good idea to use single enum for storing all constants. Instead we can use one enum for each group of constants.

Let us suppose you have maintaining some colour codes then better to have Colour enum instead of saving as constants.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM