Я не получил полного понимания статических конструкторов в Java. Если это разрешено, почему это разрешено? В каких сценариях вы бы это использовали? Какой цели это будет служить? Может кто-нибудь дать мне простой пример, пожалуйста?
11
Ответы:
Строго говоря, в Java нет статических конструкторов, поскольку конструктор по определению не может быть статическим. То, на что вы ссылаетесь, называется «статическим блоком инициализации». Конструктор подразумевает, что вы создаете объект. Вы не можете иметь конструктор для класса, потому что класс не является его экземпляром. Это просто класс. То, что «конструирует» класс, называется компилятором (или виртуальной машиной, в зависимости от того, что подразумевается под «конструкциями»), и если вы попадаете в конструирование кода внутри другого кода, вы попадаете в процесс генерации кода, который совершенно другой зверь.
За исключением всех придирок, статический блок инициализации используется для инициализации сложных статических (или уровня класса) полей для класса. Обычно они используются для инициализации вещей, которые либо не могут быть инициализированы в одной строке, либо требуют, чтобы сначала был инициализирован какой-либо другой объект (который может быть или не быть в классе, в котором реализован статический блок).
По сути, их можно использовать, чтобы сказать классу: «Эй, установите переменную A на это значение FIRST, а затем, как только это будет сделано, используйте значение A для инициализации B.» Поскольку Java требует, чтобы стандартная инициализация поля выполнялась либо внутри конструктора или метода, либо с помощью вызова конструктора или метода (если это не литерал), они могут быть удобным методом для инициализации сложных статических объектов.
Блоки статической инициализации не нужны слишком часто, и, как правило, их следует избегать, если они не имеют реального использования. Не поймите меня неправильно, они занимают свое место в Java, но, как и многие другие вещи (такие как операторы break, return, switch и goto), их можно легко использовать чрезмерно, что снижает их читаемость и удобство сопровождения кода. -на базе они используются в.
Краткий пример используемого статического блока инициализации может быть следующим (согласно превосходному объяснению статических блоков инициализации, найденных здесь ):
Код:
Выход:
Некоторые примеры, которые они перечисляют, когда статические блоки могут быть полезны:
Некоторые причины НЕ использовать статические блоки (в других ситуациях):
this
ключевое слово, так как нет экземпляра.Я должен отметить: в то время как некоторые языки (такие как C #) могут иметь синтаксис для «конструкторов», которые являются статическими, эти «конструкторы» функционируют почти так же, как статические блоки инициализации в Java, и рассматриваются многими (включая меня) как неправильные в языке, учитывая основную концепцию конструктора ООП .
источник
он используется для инициализации полей, которые сложнее, чем просто его присвоение:
невозможно заполнить карту при инициализации (если вы не используете анонимный взлом подкласса), так что это лучший способ гарантировать ее заполнение перед первым использованием
Вы также можете сделать это, чтобы перехватить отмеченные исключения при инициализации
источник
Ответ Гургадургена, вероятно, то, что вы ищете, но я просто добавлю пару других моментов, которые иногда игнорируются, когда кто-то хочет «статический конструктор».
Если вам нужен статический метод, который создает экземпляр вашего класса, вы можете создать статический метод, который просто вызывает конструктор класса.
Это производит вывод:
Другой причиной создания статического метода для создания экземпляра является случай, когда вы хотите убедиться, что в любой момент времени существует ровно один экземпляр вашего класса; это называется синглтон . По соглашению такой класс должен предоставлять статический метод, вызываемый
getInstance()
для получения единственного и единственного экземпляра, который обрабатывается как «синглтон».Это производит следующее.
Сохраняя ссылку на синглтон, а затем изменяя его, следующий вызов
getInstance()
получает этот модифицированный синглтон.Соблазнительно использовать синглтоны как способ начать создавать глобальные переменные для вашего приложения. В некоторых случаях это может быть полезно, но также может привести к неприятностям. В частности, я столкнулся с интересной ошибкой при разработке приложения для Android, где экземпляры синглтона могли потеряться. Переход от одного действия к другому может иногда привести к тому, что JVM будет использовать новый «загрузчик классов», который не будет знать о синглтоне, который статически хранился предыдущим загрузчиком классов.
источник
Хотя я понимаю, что многие считают понятие «статический конструктор» неправильным, я не верю, что это так. Проблема заключается в создании классов и их экземпляров объектов . В других потоках говорилось, что создание класса - это работа компилятора. Даже в Java это только наполовину правда.
Компилятор создает скаффолд для каждого определения класса. Каркас содержит метаданные о классе и о том, какие экземпляры должны быть в них во время создания. Если класс определяет поле, которому присваивается постоянное примитивное значение, то это значение включается в каркас компилятором. Для любых других присваиваемых типов значений компилятор генерирует процедуру инициализации, которая должна выполняться 1 раз, до создания первого экземпляра класса, который обновляет каркас с соответствующими значениями. Это обновление не может быть сделано компилятором.
Поскольку это единовременное обновление скаффолда часто является критической предпосылкой для правильного функционирования конструкторов экземпляра, также разумно назвать его типом конструктора. Вот почему в распространенных ОО-языках, поддерживающих эту концепцию, он называется статическим конструктором. Концепция, стоящая за статическими блоками инициализации в Java, является не более чем семантическим изменением, чтобы соответствовать идее, что программист на Java должен быть независимым как от системы, так и от реализации.
источник
Как уже говорили другие ответы, вы можете написать статические методы, которые создают объект. Это обходит отсутствие именованных конструкторов в Java (и во многих других языках. Delphi поддерживает именованные конструкторы). Вы можете играть с типами и порядком параметров, но это может привести к нечеткому и хрупкому коду.
Например, мы могли бы придумать сценарий, в котором ваш объект может быть построен из строки XML или строки JSON. Вы можете написать такие методы, как:
Я использовал это очень редко в качестве альтернативы конструктору без параметров с именованными методами инициализации:
Вы можете рассматривать статический метод create как реализацию шаблона компоновщика внутри вашего класса.
источник
Вы можете просмотреть «статический» раздел как конструктор уровня класса, используемый для инициализации свойств класса (статический в Java). Как и «обычный» конструктор, он используется для инициализации свойств уровня экземпляра.
источник