【问题标题】:Enums as replacement of Constants in Java枚举作为 Java 中常量的替代品
【发布时间】:2014-08-22 20:18:20
【问题描述】:

我现在听说我们应该使用枚举而不是常量。 在所有情况下都有可能吗? 枚举是否可以替代常量

在下面的示例中,我在常量文件中定义了常量,并且 ConstantsTest 使用它们

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

}

请在我的示例示例中提出建议枚举会更好,或者我目前使用常量的方法是否足够好

【问题讨论】:

标签: java enums constants


【解决方案1】:

只有我们可以将枚举用于单个组中的常量值。 让我们假设:周、月、颜色、性别、流程状态

使用单个枚举来存储所有常量并不是一个好主意。相反,我们可以为每组常量使用一个枚举。

让我们假设您维护了一些颜色代码,然后最好使用 Color 枚举而不是保存为常量。

【讨论】:

    【解决方案2】:

    你应该使用枚举这个代码

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

    【讨论】:

      【解决方案3】:

      在您的特定情况下,使用枚举是经典解决方案。

      首先,让我们将Constants 重写为枚举:

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

      现在不用写了:

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

      您可以使用switch/case 甚至更好地定义:define 方法(让我们将其称为action() 到枚举中并从您的代码中调用它。参见上面Operation 枚举中的示例。在这种情况下,您的代码变得微不足道: 不再有if/else 或 switch 语句。一切都很简单。验证在编译时完成:您在枚举中定义了抽象方法,如果不为其实现此方法,则无法向枚举添加另一个元素。使用 @987654328 时不会发生这种情况@结构的维护是程序员的责任。

      我只知道枚举的一个限制:在注释中使用字符串常量。有很多带有字符串属性的注释。例如XmlElement(name="foo")。即使你定义了枚举

      enum FooBar {
          foo, bar
      }
      

      你不能在注释中使用它:

      @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 
      

      在所有其他情况下,我更喜欢枚举。

      【讨论】:

        【解决方案4】:

        对于提供的示例,常量会更好。接口变量默认为public static final。

        public static final String ACCOUNT="Account";
        

        Why are interface variables static and final by default?

        【讨论】:

        • 它隐含在接口定义中,只是想提一下。
        • 我已经使用接口来定义常量..所以它们默认是 public static final
        • @Shirish - 这篇文章已经有一年了。所以我希望你一定已经停止使用“常量接口”并开始使用无法实例化的枚举或类。
        【解决方案5】:

        你弄错了枚举,你不应该创建一个枚举而不是常量:一个枚举是一个相关的常量,例如:

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

        来自docs

        枚举类型是一种特殊的数据类型,它使变量能够 一组预定义的常量。

        【讨论】:

          【解决方案6】:

          Enum 没有为使用它的类定义 contractinterface 可以。使用 Enum 的类不是 Enum 类型。实现接口的类实际上与接口的类型相同(接口是父级..并且可以更改引用)。考虑到这些设计问题。告诉我,你的方法正确吗?

          【讨论】:

          • 我的类没有实现接口。我使用接口来定义常量....所以默认情况下它们是 public static final ...我不必为每个常量都编写它
          • @Shree - 严格来说.. Interface 隐含地定义了一个牢不可破的合约。你可能没有使用它。但是您仍然为其提供功能(这与 OOP 概念背道而驰)。
          • @Shree 你让懒惰支配了你的设计?
          • 好吧,我已经浏览了 stackoverflow.com/questions/320588/…"> URL,这让我很好地了解了为什么使用接口来编写常量是不好的做法...... . 我同意你的观点......我会在未来遵循它......但主要问题是关于使用枚举作为常量的替代品。
          猜你喜欢
          • 2011-08-08
          • 2011-07-09
          • 2013-08-01
          • 2014-09-26
          • 1970-01-01
          • 2017-02-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多