У меня есть класс, полный служебных функций. Создание его экземпляра не имеет семантического смысла, но я все же хочу вызывать его методы. Как лучше всего с этим справиться? Статический класс? Аннотация?
@matt b: Как указывает Дэвид Роблес в своем ответе, вам не нужно делать класс окончательным ... он не может быть подклассом, потому что подкласс не сможет вызвать конструктор суперкласса, потому что он частный. Однако ... нет ничего плохого в том, чтобы быть откровенным. Но яфу :-).
Правило 4: Обеспечьте невозможность создания экземпляров с помощью частного конструктора
- Попытка обеспечить неинстанциональность путем создания абстрактного класса не работает.
- Конструктор по умолчанию создается только в том случае, если класс не содержит явных конструкторов, поэтому класс можно сделать неинстанцируемым, включив частный конструктор:
// Noninstantiable utility classpublicclassUtilityClass{// Suppress default constructor for noninstantiabilityprivateUtilityClass(){thrownewAssertionError();}}
Поскольку явный конструктор является закрытым, он недоступен вне класса. AssertionError не является строго обязательным, но он обеспечивает страховку на случай, если конструктор будет случайно вызван из класса. Это гарантирует, что класс никогда не будет создан ни при каких обстоятельствах. Эта идиома слегка противоречит здравому смыслу, поскольку конструктор предоставляется явно, поэтому его нельзя вызвать. Поэтому разумно включить комментарий, как показано выше.
В качестве побочного эффекта эта идиома также предотвращает создание подкласса класса. Все конструкторы должны вызывать конструктор суперкласса, явно или неявно, и у подкласса не будет доступного конструктора суперкласса для вызова.
Просто чтобы плыть против течения, статические члены и классы не участвуют в объектно-ориентированном взаимодействии и поэтому являются злом. Нет, не зло, но серьезно, я бы порекомендовал обычный класс с одноэлементным шаблоном для доступа. Таким образом, если вам нужно переопределить поведение в любых случаях в будущем, это не будет серьезным переоснащением. OO твой друг :-)
синглтон не больше зла , чем инъекции зависимостей :)
irreputable
12
ОО имеет свое место, но бывают случаи, когда это просто непрактично или было бы пустой тратой ресурсов - например, что-то столь же простое, как Math.abs (). Нет причин создавать экземпляр объекта только ради создания экземпляра объекта, когда вызов статического метода с таким же успехом послужил бы вам без каких-либо дополнительных затрат на объектно-ориентированные разработки. ;)
ограбить
2
@rob re OO, я согласен, Math.Abs, вероятно, никогда не нуждается в экземпляре. Когда я слышу «у меня есть служебный класс», я вижу Math.Avg (), где вам теперь нужно добавить поддержку для средневзвешенного значения. Я вижу генератор URL-адресов, параметры входа и выхода, которые необходимо отредактировать для поддержки href, или только URL-адреса и т. Д. По этим причинам использование служебного класса на основе объектно-ориентированного программирования может окупиться. Кроме того, теперь я откажусь от стандартной тактики ОО-защиты, тестирования! / me ducks
Беннет Дилл
3
прокомментируйте аргументы "частного конструктора": давайте, разработчики не такие тупые; но они ленивы. создание объекта, а затем вызов статических методов? не произойдет.
не тратьте слишком много времени, чтобы убедиться, что вашим классом нельзя злоупотреблять. верьте своим коллегам. и всегда есть способ злоупотребить вашим классом, независимо от того, как вы его защищаете. единственное, чем нельзя злоупотреблять, - это совершенно бесполезная вещь.
Кто-то, кто видел (в производственном коде, а не только в студенческом коде) object.staticMethod Я думаю, вы переоцениваете способности Джо Случайного Программиста! :-P
TofuBeer
2
Конечный класс и частный конструктор (хорошо, но не обязательно)
Нет смысла объявлять класс как static. Просто объявите его методы staticи вызовите их из имени класса как обычно, как класс Java Math .
Кроме того, даже если не обязательно делать конструктор закрытым, это хорошая идея. Если пометить конструктор как закрытый, другие люди не смогут создавать экземпляры вашего класса, а затем вызывать статические методы из этих экземпляров. (Эти вызовы работают точно так же в Java, они просто вводят в заблуждение и ухудшают читаемость вашего кода.)
Ответы:
Частный конструктор и статические методы в классе, помеченном как final.
источник
Согласно великой книге «Эффективная Java» :
Правило 4: Обеспечьте невозможность создания экземпляров с помощью частного конструктора
- Попытка обеспечить неинстанциональность путем создания абстрактного класса не работает.
- Конструктор по умолчанию создается только в том случае, если класс не содержит явных конструкторов, поэтому класс можно сделать неинстанцируемым, включив частный конструктор:
Поскольку явный конструктор является закрытым, он недоступен вне класса. AssertionError не является строго обязательным, но он обеспечивает страховку на случай, если конструктор будет случайно вызван из класса. Это гарантирует, что класс никогда не будет создан ни при каких обстоятельствах. Эта идиома слегка противоречит здравому смыслу, поскольку конструктор предоставляется явно, поэтому его нельзя вызвать. Поэтому разумно включить комментарий, как показано выше.
В качестве побочного эффекта эта идиома также предотвращает создание подкласса класса. Все конструкторы должны вызывать конструктор суперкласса, явно или неявно, и у подкласса не будет доступного конструктора суперкласса для вызова.
источник
AssertionError
другие альтернативы, напримерIllegalStateException
,UnsupportedOperationException
и т. Д.?Похоже, у вас есть служебный класс, похожий на java.lang.Math .
Подход есть финальный класс с частным конструктором и статическими методами.
Но остерегайтесь того, что это делает для тестируемости, я рекомендую прочитать эту статью
Статические методы - смерть тестируемости.
источник
Просто чтобы плыть против течения, статические члены и классы не участвуют в объектно-ориентированном взаимодействии и поэтому являются злом. Нет, не зло, но серьезно, я бы порекомендовал обычный класс с одноэлементным шаблоном для доступа. Таким образом, если вам нужно переопределить поведение в любых случаях в будущем, это не будет серьезным переоснащением. OO твой друг :-)
Мои 0,02 доллара
источник
прокомментируйте аргументы "частного конструктора": давайте, разработчики не такие тупые; но они ленивы. создание объекта, а затем вызов статических методов? не произойдет.
не тратьте слишком много времени, чтобы убедиться, что вашим классом нельзя злоупотреблять. верьте своим коллегам. и всегда есть способ злоупотребить вашим классом, независимо от того, как вы его защищаете. единственное, чем нельзя злоупотреблять, - это совершенно бесполезная вещь.
источник
источник
Нет смысла объявлять класс как
static
. Просто объявите его методыstatic
и вызовите их из имени класса как обычно, как класс Java Math .Кроме того, даже если не обязательно делать конструктор закрытым, это хорошая идея. Если пометить конструктор как закрытый, другие люди не смогут создавать экземпляры вашего класса, а затем вызывать статические методы из этих экземпляров. (Эти вызовы работают точно так же в Java, они просто вводят в заблуждение и ухудшают читаемость вашего кода.)
источник
Вы можете использовать аннотацию @UtilityClass из lombok https://projectlombok.org/features/experimental/UtilityClass
источник