Частный конструктор в абстрактном классе

В Java, какова цель использования частного конструктора в абстрактном классе?

В обзоре я получил этот вопрос, и мне любопытно, для какой ситуации нам нужно использовать конструктор таким образом?

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

Может быть, есть более элегантное использование?

Ответ 1

Если конструктор private является конструктором только класса, то причина очевидна: для предотвращения подкласса. Некоторые классы служат только как держатели для статических полей/методов и не хотят быть ни инстанцированными, ни подклассами. Обратите внимание, что модификатор abstract в этом случае является избыточным или без него, без возможности создания экземпляра. Как отмечает @JB Nizet ниже, модификатор abstract также является плохой практикой, потому что он посылает неверные сигналы клиентам класса. Класс должен быть фактически final.

Существует еще один вариант использования: он может иметь abstract class только с конструкторами private, который содержит свои собственные подклассы как вложенные классы. Эта идиома гарантирует, что эти вложенные классы являются единственными подклассами. Фактически, enum в Java использует только эту идиому.

Если вокруг есть другие конструкторы, ну, в конструкторе private нет ничего особенного. Он используется в классе abstract, как и в любом другом.

Ответ 2

Единственное, о чем я могу думать, это повторное использование общего кода, совместно используемого другими (защищенными) конструкторами. Затем они могли бы вызвать частный конструктор в своей первой строке.

Ответ 3

Иногда конструктор no-arg по умолчанию становится закрытым, и предоставляется другой конструктор, который принимает аргументы. Этот конструктор может затем вызывать другие частные конструкторы. Это заставляет реализации поставлять эти аргументы, которые могут гарантировать, что какая-то переменная всегда инициализирована, хотя это не обычная практика (по моему опыту). Если это требование, вам лучше проверить свои переменные и выбросить IllegalArgumentExeption, объяснив, почему переменная должна быть инициализирована.

Если вы создаете абстрактный класс только с частными конструкторами, класс практически бесполезен, поскольку никакие экземпляры не могут быть созданы. Если целью является создание класса утилиты только с статическими методами (например, с классом Math в пакете java.lang), частные конструкторы приемлемы, однако класс должен быть помечен как final вместо того, чтобы обозначить класс как абстрактный, класс должен быть расширен.

Ответ 4

  • Как уже упоминалось, используется как обычный конструктор только для внутреннего использования.

  • Абстрактные или не абстрактные, это не редкость для объявления частного конструктора по умолчанию в классе, содержащем только статические общедоступные методы [вспомогательные методы], чтобы предотвратить создание экземпляра класса.

Ответ 5

нет другого элегантного использования возможно

Ответ 6

Закрытый конструктор в абстрактном классе также может служить для целей sealed классов (как в Scala, Kotlin и т.д.). Поскольку вы все еще можете предоставлять подклассы из абстрактного класса, но посторонние не могут расширять/реализовывать (как ответил @Marko Topolnik).

Похоже, мы получим sealed interface для более чистой поддержки этого. Смотрите https://openjdk.java.net/jeps/8222777