Частный конструктор в абстрактном классе
В 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