Перечисления как замена констант в Java

1

Сегодня я услышал, что мы должны использовать Enums вместо Constants. Возможно ли это во всех случаях? Являются ли перечисления заменой констант?

В приведенном ниже примере у меня есть константы, определенные в файле Constants, и 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
         }
     }
}

}

Пожалуйста, предложите в моем примере пример перечислений будет лучше, или мой текущий подход к использованию констант достаточно хорош?

  • 2
    Похоже, дубликат констант JAVA: перечисления VS классы VS интерфейсы , с дополнительным дублированием кандидата перечислений для констант в Java - это хороший стиль?
  • 0
    С точки зрения дизайна, ваш код дает совершенно другое значение по сравнению с Enums.
Показать ещё 5 комментариев
Теги:
enums
constants

6 ответов

4
Лучший ответ

В вашем конкретном случае использование enums является классическим решением.

Во-первых, позвольте переписать свои 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 или даже лучше не определить: определить метод (пусть называют это action() в перечислении и вызывать его из кода Смотрите пример в. Operation перечисления выше в этом случае вы код становится тривиальным:. не более if/else или switch. Все просто: проверка выполняется во время компиляции: вы определили абстрактный метод в перечислении, вы не можете добавить еще один элемент в перечисление без реализации этого метода для него. Этого не происходит при использовании if/else структурного обслуживания, из которого является ответственностью программиста.

Я знаю только одно ограничение перечислений: использование аннотаций строки в константах. Существует много аннотаций со строковыми атрибутами. Например 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 

Во всех остальных случаях я предпочитаю перечисление.

  • 0
    +1 .. действительно хороший и исчерпывающий ответ ..
  • 0
    Это действительно хороший пример, который вы предоставили
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();
   }
 }
}
0

Только мы можем использовать Enums для постоянных значений, которые находятся в одной группе. Предположим: недели, месяцы, цвета, пол, состояния процесса

Не рекомендуется использовать единый enum для хранения всех констант. Вместо этого мы можем использовать одно перечисление для каждой группы констант.

Предположим, что у вас есть некоторые цветовые коды, тогда лучше иметь цветное перечисление вместо сохранения в качестве констант.

0

Enum не определяет contract для класса, использующего его, interface делает. Класс, который использует Enum, не относится к типу Enum. Класс, который реализует интерфейс, фактически имеет тот же тип, что и интерфейс (интерфейс является родительским.. и ссылка может быть изменена). Учитывая эти проблемы проектирования. Скажите, ваш подход правильный?

  • 0
    мой класс не реализует интерфейс. Я использовал интерфейс для определения констант .... так что они по умолчанию public static final ... Мне не нужно писать это для всех констант
  • 0
    @Shree - Строго говоря. Interface неявно определяет неразрывный контракт. Возможно, вы не используете его. Но вы все еще предоставляете возможность для этого (что противоречит концепциям ООП).
Показать ещё 2 комментария
0

Вы ошиблись в перечислении, вам не нужно создавать перечисление вместо константы: enum - это группа констант, которые связаны, например:

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

Из документов:

Тип перечисления - это особый тип данных, который позволяет переменной представлять собой набор предопределенных констант.

0

Константы будут лучше для приведенного примера. По умолчанию переменные интерфейса являются общедоступными.

public static final String ACCOUNT="Account";

См. Почему по умолчанию переменные интерфейса статичны и окончательны?

  • 0
    Это подразумевается в определении интерфейса, но я просто хотел упомянуть об этом.
  • 0
    Я использовал интерфейс для определения констант .. поэтому они по умолчанию public static final
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню