Предположим, вам нужно определить класс, который все, что он делает, хранит константы.
public static final String SOME_CONST = "SOME_VALUE";
Каков предпочтительный способ сделать это?
- Интерфейс
- Абстрактный класс
- Финальный класс
Какой из них использовать и почему?
Разъяснения к некоторым ответам:
Перечисления - я не буду использовать перечисления, я ничего не перечисляю, а просто собираю некоторые константы, которые никак не связаны друг с другом.
Интерфейс - я не собираюсь устанавливать какой-либо класс как тот, который реализует интерфейс. Просто хочу , чтобы использовать интерфейс для вызова констант следующим образом: ISomeInterface.SOME_CONST
.
java
class-constants
Юваль Адам
источник
источник
Ответы:
Используйте последний класс. для простоты вы можете затем использовать статический импорт для повторного использования ваших значений в другом классе
public final class MyValues { public static final String VALUE1 = "foo"; public static final String VALUE2 = "bar"; }
в другом классе:
import static MyValues.* //... if(variable.equals(VALUE1)){ //... }
источник
VALUE1.equals(variable)
поскольку он избегает NPE.В вашем пояснении сказано: «Я не буду использовать перечисления, я ничего не перечисляю, просто собираю некоторые константы, которые никак не связаны друг с другом».
Если константы никак не связаны друг с другом, зачем вам собирать их вместе? Поместите каждую константу в класс, с которым она наиболее тесно связана.
источник
Мои предложения (в порядке убывания предпочтения):
1) Не делай этого . Создайте константы в реальном классе там, где они наиболее актуальны. Наличие класса / интерфейса «мешка констант» на самом деле не соответствует лучшим практикам объектно-ориентированного проектирования.
Я, как и все остальные, время от времени игнорирую №1. Если вы собираетесь это сделать, то:
2) final класс с частным конструктором. Это, по крайней мере, предотвратит злоупотребление вашим «набором констант», расширяя / реализуя его, чтобы получить легкий доступ к константам. (Я знаю, вы сказали, что не сделаете этого, но это не значит, что кто-то придет после вас)
3) interface Это будет работать, но я не предпочитаю упоминать возможное злоупотребление в №2.
В общем, то, что это константы, не означает, что вы не должны применять к ним обычные принципы oo. Если никто, кроме одного класса, не заботится о константе - она должна быть закрытой и принадлежать этому классу. Если только тесты заботятся о константе - она должна быть в тестовом классе, а не в производственном коде. Если константа определена в нескольких местах (а не просто случайно в одном и том же) - произведите рефакторинг, чтобы исключить дублирование. И так далее - относитесь к ним, как к методу.
источник
Как отмечает Джошуа Блох в Effective Java:
Вы можете использовать Enum, если все ваши константы связаны (например, имена планет), поместить значения констант в классы, с которыми они связаны (если у вас есть к ним доступ), или использовать не поддающийся инстанции служебный класс (определите частный конструктор по умолчанию) .
class SomeConstants { // Prevents instanciation of myself and my subclasses private SomeConstants() {} public final static String TOTO = "toto"; public final static Integer TEN = 10; //... }
Затем, как уже было сказано, вы можете использовать статический импорт для использования ваших констант.
источник
Я предпочитаю вообще не делать этого. Возраст констант практически умер, когда в Java 5 были введены типы безопасных перечислений. И еще до этого Джош Блох опубликовал (чуть более многословную) версию этого, которая работала на Java 1.4 (и ранее).
Если вам не нужна совместимость с каким-либо унаследованным кодом, действительно нет причин использовать именованные строковые / целочисленные константы.
источник
Просто используйте последний класс.
Если вы хотите иметь возможность добавлять другие значения, используйте абстрактный класс.
Использование интерфейса не имеет особого смысла, интерфейс должен указывать контракт. Вы просто хотите объявить некоторые постоянные значения.
источник
Разве перечисления не лучший выбор для такого рода вещей?
источник
enum
s в порядке. IIRC, один элемент в эффективной Java (2-е изд.) Имеетenum
константы, перечисляющие стандартные параметры, реализующие [ключевое слово Java]interface
для любого значения.Я предпочитаю использовать [ключевое слово Java] вместо
interface
afinal class
для констант. Вы неявно получаетеpublic static final
. Некоторые люди будут утверждать, что онinterface
позволяет плохим программистам реализовать его, но плохие программисты будут писать отстойный код, что бы вы ни делали.Что выглядит лучше?
public final class SomeStuff { private SomeStuff() { throw new Error(); } public static final String SOME_CONST = "Some value or another, I don't know."; }
Или:
public interface SomeStuff { String SOME_CONST = "Some value or another, I don't know."; }
источник
Или 4. Поместите их в класс, содержащий логику, которая больше всего использует константы.
... извините, не удержался ;-)
источник
Одним из недостатков частного конструктора является то, что метод не может быть протестирован.
Enum по своей природе хорошо подходит для применения в конкретном типе домена, его применение к децентрализованным константам выглядит недостаточно хорошо
Концепция Enum такова: «Перечисления - это наборы тесно связанных элементов».
Расширять / реализовывать постоянный интерфейс - плохая практика, трудно думать о необходимости расширения неизменной константы вместо того, чтобы ссылаться на нее напрямую.
Если применить качественный инструмент, такой как SonarSource, есть правила, вынуждающие разработчика отказаться от постоянного интерфейса, это неудобно, так как многие проекты пользуются постоянным интерфейсом и редко можно увидеть, как что-то «расширяется» на постоянных интерфейсах.
источник