У меня есть класс, полный служебных функций. Создание его экземпляра не имеет семантического смысла, но я все же хочу вызывать его методы. Как лучше всего с этим справиться? Статический класс? Аннотация?
У меня есть класс, полный служебных функций. Создание его экземпляра не имеет семантического смысла, но я все же хочу вызывать его методы. Как лучше всего с этим справиться? Статический класс? Аннотация?
Ответы:
Частный конструктор и статические методы в классе, помеченном как final.
Согласно великой книге «Эффективная Java» :
Правило 4: Обеспечьте невозможность создания экземпляров с помощью частного конструктора
- Попытка обеспечить неинстанциональность путем создания абстрактного класса не работает.
- Конструктор по умолчанию создается только в том случае, если класс не содержит явных конструкторов, поэтому класс можно сделать неинстанцируемым, включив частный конструктор:
// Noninstantiable utility class
public class UtilityClass
{
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
}
Поскольку явный конструктор является закрытым, он недоступен вне класса. AssertionError не является строго обязательным, но он обеспечивает страховку на случай, если конструктор будет случайно вызван из класса. Это гарантирует, что класс никогда не будет создан ни при каких обстоятельствах. Эта идиома слегка противоречит здравому смыслу, поскольку конструктор предоставляется явно, поэтому его нельзя вызвать. Поэтому разумно включить комментарий, как показано выше.
В качестве побочного эффекта эта идиома также предотвращает создание подкласса класса. Все конструкторы должны вызывать конструктор суперкласса, явно или неявно, и у подкласса не будет доступного конструктора суперкласса для вызова.
AssertionError
другие альтернативы, например IllegalStateException
, UnsupportedOperationException
и т. Д.?
Похоже, у вас есть служебный класс, похожий на java.lang.Math .
Подход есть финальный класс с частным конструктором и статическими методами.
Но остерегайтесь того, что это делает для тестируемости, я рекомендую прочитать эту статью
Статические методы - смерть тестируемости.
Просто чтобы плыть против течения, статические члены и классы не участвуют в объектно-ориентированном взаимодействии и поэтому являются злом. Нет, не зло, но серьезно, я бы порекомендовал обычный класс с одноэлементным шаблоном для доступа. Таким образом, если вам нужно переопределить поведение в любых случаях в будущем, это не будет серьезным переоснащением. OO твой друг :-)
Мои 0,02 доллара
прокомментируйте аргументы "частного конструктора": давайте, разработчики не такие тупые; но они ленивы. создание объекта, а затем вызов статических методов? не произойдет.
не тратьте слишком много времени, чтобы убедиться, что вашим классом нельзя злоупотреблять. верьте своим коллегам. и всегда есть способ злоупотребить вашим классом, независимо от того, как вы его защищаете. единственное, чем нельзя злоупотреблять, - это совершенно бесполезная вещь.
Нет смысла объявлять класс как static
. Просто объявите его методы static
и вызовите их из имени класса как обычно, как класс Java Math .
Кроме того, даже если не обязательно делать конструктор закрытым, это хорошая идея. Если пометить конструктор как закрытый, другие люди не смогут создавать экземпляры вашего класса, а затем вызывать статические методы из этих экземпляров. (Эти вызовы работают точно так же в Java, они просто вводят в заблуждение и ухудшают читаемость вашего кода.)
Вы можете использовать аннотацию @UtilityClass из lombok https://projectlombok.org/features/experimental/UtilityClass