Для чего в java статические блоки

10 заметок о модификаторе Static в Java

Статические поля

Статический блок

Статический метод

Статический класс в Java

Что должен знать каждый программист о модификаторе Static в Java

Вы НЕ можете получить доступ к НЕ статическим членам класса, внутри статического контекста, как вариант, метода или блока. Результатом компиляции приведенного ниже кода будет ошибка:

В отличие от локальных переменных, статические поля и методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите — «залочивании» классом. Поэтому при использовании статических переменных, убедитесь, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких как «состояние гонки» (race condition).

Статические методы имеют преимущество в применении, т.к. отсутствует необходимость каждый раз создавать новый объект для доступа к таким методам. Статический метод можно вызвать, используя тип класса, в котором эти методы описаны. Именно поэтому, подобные методы как нельзя лучше подходят в качестве методов-фабрик ( factory ), и методов-утилит ( utility ). Класс java.lang.Math — замечательный пример, в котором почти все методы статичны, по этой же причине классы-утилиты в Java финализированы ( final ).

Другим важным моментом является то, что вы НЕ можете переопределять ( Override ) статические методы. Если вы объявите такой же метод в классе-наследнике ( subclass ), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса ( superclass ) вместо переопределения. Это явление известно как сокрытие методов ( hiding methods ). Это означает, что при обращении к статическому методу, который объявлен как в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:

Внутри родительского класса/статического метода

Модификатор static также может быть объявлен в статичном блоке, более известным как «Статический блок инициализации» ( Static initializer block ), который будет выполнен во время загрузки класса. Если вы не объявите такой блок, то Java соберёт все статические поля в один список и выполнит его во время загрузки класса. Однако, статичный блок НЕ может пробросить перехваченные исключения, но может выбросить не перехваченные. В таком случае возникнет «Exception Initializer Error». На практике, любое исключение возникшее во время выполнения и инициализации статических полей, будет завёрнуто Java в эту ошибку. Это также самая частая причина ошибки «No Class Def Found Error», т.к. класс не находился в памяти во время обращения к нему.

Полезно знать, что статические методы связываются во время компиляции, в отличие от связывания виртуальных или не статических методов, которые связываются во время исполнения на реальном объекте. Следовательно, статические методы не могут быть переопределены в Java, т.к. полиморфизм во время выполнения не распространяется на них. Это важное ограничение, которое необходимо учитывать, объявляя метод статическим. В этом есть смысл, только тогда, когда нет возможности или необходимости переопределения такого метода классами-наследниками. Методы-фабрики и методы-утилиты хорошие образцы применения модификатора static. Джошуа Блох выделил несколько преимуществ использования статичного метода-фабрики перед конструктором, в книге «Effective Java», которая является обязательной для прочтения каждым программистом данного языка.

На этом всё. Все вышеперечисленные пункты о модификаторе static в Java обязан знать каждый программист. В данной статье была рассмотрена базовая информация о статических переменных, полях, методах, блоках инициализации и импорте. В том числе некоторые важные свойства, знание которых является критичным при написании и понимании программ на Java. Я надеюсь, что каждый разработчик доведёт свои навыки использования статических концептов до совершенства, т.к. это очень важно для серьёзного программирования.»

Источник

Для чего в java статические блоки

Ключевое слово static в Java

Например, у него может быть цвет, материал изготовления, форма, он может состоять также из более мелких узлов(вспомогательных приборов) и т.д

Все это является свойствами объекта, они уникальны и для каждого прибора они свои.

Работая с объектом мы используем эти свойства, изменяем их и реагируем на поведение объекта.

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

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

В качестве примера, рассмотрим метод, который печатает в консоль число, которое передается аргументом в этот метод:

Т.е такой метод не связан с объектом класса, он связан только с классом, в котором объявлен.

А раз он не связан с объектом, то и объект, для использования этого метода, не нужен. Нужен только класс, в котором объявлен этот метод.

Указав модификатор static у поля или метода класса, вы тем самым говорите: это поле или метод принадлежат именно классу.

Если поле или метод принадлежит классу, то для всех объектов класса это поле или метод будет одно, так как оно уже не принадлежит объекту. При этом изменение этого поля у одного объекта влечет его изменение у всех объектов.

Грубо говоря, если вы объявляете поле класса статическим, то вы как бы расшариваете это поле для всех объектов.

Представьте себе документ, который редактирует несколько пользователей. Если один из пользователй изменяет какое-то слово или абзац, то документ меняется у всех пользователей.

Это довольно логично, так как экземпляра объекта класса может еще не быть, поэтому доступа до переменной count нет.

Вообще говоря, static крайне плохо ложится на ООП парадигму и в идеале надо стараться свести использование static методов и изменяемых переменных к минимуму.

Где используется static

Ключевое слово static может быть использовано при объявлении:

Статические методы принадлежат классу, а значит, для их использования не нужно создавать экземпляр объекта класса.

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

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

Если же для работы статического метода передаваемых ему аргументов недостаточно, то это верный признак того, что стоит крепко задуматься: «А должен ли он вообще быть статическим?».

Статические методы применяются также при использовании factory и builder паттернов.

Подробнее об этом в Паттерны.

Создание экземпляров объектов

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

Обычно внутри таких методов добавляется еще какая-то логика или оптимизация.

Наиболее часто используемые значения также кешируются.

Представим для примера, что мы хотим посчитать количество созданных экзмепляров класса:

Но в основном статические поля используются для создания констант:

Про константы и их оформление можно прочесть вот тут.

Статические блоки кода

Инициализация статического блока кода выполняется на этапе загрузки класса, грубо говоря, в момент первого к нему обращения. Благодаря этому статические блоки кода используются тогда, когда необходимо выполнить какую-то логику еще до создания экземпляра объекта.

С небольшой оговоркой можно считать, что это конструктор для всего класса.

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

Выглядит синтаксис статического блока вот так:

Статических блоков может быть несколько, их выполнение будет происходить в порядке объявления.

Статические блоки можно использовать для инициализации статических полей, например:

Т.е у нас есть некоторый каталог и есть данные для заполнения.

Для этого мы и использовали статический блок кода, и он выполнился ровно один раз при иницализации класса, тем самым мы один раз заполнили наш каталог и далее можем его использовать.

Так вот, загрузку драйвера как раз делают в статическом блоке:

Подробнее о порядке выполнения кода при инициализации класса: Порядок инициализации полей класса в Java.

Статические вложенные классы

В Java можно объявить класс внутри другого класса.

Для иллюстрации вышесказанного:

Понятно, что nested класссы принадлежат outer классу, в то время как inner классы принадлежат уже экземпляру объекта класса.

Зачем же вообще нужны nested классы?

Например, вы пишите реализацию связного списка.

Логично, что исходя из этого делать отдельный public класс излишне.

Объявив же в такой ситуации вложенный класс, вы добьетесь сразу нескольких преимуществ:

Логически сгруппируете классы, которые используются в одном месте

Если класс полезен только для одного стороннего класса, то логично ввести его в этот класс и поддерживать вместе.

Это способ привести код к более читабельному и поддерживаемому виду.

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

Это увеличивает инкапсуляцию.

Если вложенный класс используется только внутри стороннего класса, логично скрыть его и использовать лишь внутри. Аналогично с тем, как мы объявляем private поля.

Подробнее о вложенных классах: Вложенные классы в Java.

Как стоит обращаться к статическим полям или методам

Если коротко, то раз поле или метод принадлежит классу, то и обращаться к нему необходимо через имя класса.

Если нужны подробности, то давайте посмотрим на следующий класс, содержащий статическое поле:

Мы хотим обратиться к этому полю, и возникает вопрос: как правильно это сделать?

Есть два рабочих варианта:

Так вот, сразу скажу: забудьте про первый вариант. Да, он рабочий, но делать так не стоит. Более того, это глупо!

Вспомните, что статические поля принадлежат не экземпляру объекта класса, а самому классу. Так зачем вам объект?

Для закрепления приведу следующий пример:

Возьмем класс, описанный выше, и ответим на вопрос: что будет, если мы выполним следующий код:

Ведь мы обращаемся к полю, которое принадлежит классу! А значит обращение будет не к объекту экземпляра, и код, который выполнится будет равнозначен выполнению:

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

Запомните следующее: обращение к статическим методам и полям осуществляется только через имя класса.

Еще один интересный момент состоит в том, что статический метод нельзя переопределить.

Т.е при работе с статическими методами override невозможен.

Если вы объявите один и тот же метод в классе-наследнике и в родительском классе, т.е. метод с таким же именем и сигнатурой, вы лишь спрячете метод родительского класса, но не переопределите.

При обращении к статическому методу, который объявлен как в родительском, так и в классе-наследнике, во время компиляции всегда будет вызван метод исходя из типа ссылки, по которой идет обращение к такому полю или методу.

Данный пример непрозрачно намекает, что использовать статические методы при наследовании не стоит.

При таком подходе вы легко можете допустить ошибку и не заметить ее, так как все примеры прекрасно компилируется.

Что еще надо знать про static модификатор в Java

После десериализации новый объект будет содержать его первичное значение.

Ключевое слово static может быть использовано при объявлении:

Чаще всего оно применяется для первых двух случаев.

Источник

Все о ключевых словах static и final

Для чего в java статические блоки. Смотреть фото Для чего в java статические блоки. Смотреть картинку Для чего в java статические блоки. Картинка про Для чего в java статические блоки. Фото Для чего в java статические блоки

Что такое ключевое слово static?

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

Где можно употреблять ключевое слово static?

Мы можем использовать это ключевое слово в четырех контекстах:

Рассмотрим подробнее каждый из перечисленных пунктов.

Статические методы

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

Статические переменные

При создании объектов класса в Java каждый из них содержит собственную копию всех переменных класса.

Однако, если мы объявим переменную статической, все объекты класса будут использовать одну и ту же статическую переменную. Это связано с тем, что, как и статические методы, статические переменные также связаны с классом. И объекты класса для доступа к статическим переменным создавать не нужно. Например:

В приведенном выше примере normalVariable — переменная класса, а staticVariable — статическая переменная. Если вы объявите переменную, как показано ниже:

Это похоже на доступ к статической переменной через имя класса:

Здесь статические переменные — переменные уровня класса. Поэтому, если вы обращаетесь к статическим переменным через переменную экземпляра объекта, то это отражается на соответствующей статической переменной уровня класса. Таким образом, статические переменные всегда имеют одно и то же значение. Но переменная экземпляра сохраняет отдельное значение в каждом экземпляре объекта. Таким образом, приведенный выше фрагмент кода выведет:

Статические переменные — редкость в Java. Вместо них применяют статические константы. Они определяются ключевым словом static final и представлены в верхнем регистре. Вот почему некоторые предпочитают использовать верхний регистр и для статических переменных.

Статические блоки

Здесь мы видим статический блок с синтаксисом:

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

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

Вывод приведенного выше фрагмента кода выглядит следующим образом, потому что переменная staticVariable обновлена вторым значением статического блока.

Вложенный статический класс

В Java можно объявить класс внутри другого класса. Такие классы называются вложенными классами. Они бывают двух типов: статические и нестатические.

Вложенный класс является членом заключающего его класса. Нестатические вложенные классы (внутренние классы) имеют доступ к другим членам заключающего класса, даже если они объявлены приватными. Статические вложенные классы не имеют доступа к другим членам заключающего класса.

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

Со статическим внутренним классом все иначе. Можно сказать, что если у внутреннего класса нет причин для доступа к внешнему, вы должны сделать его статическим по умолчанию.

В приведенном выше примере видно, что внутренний класс MyInnerClass может получить доступ ко всем методам и переменным внешнего, включая приватные переменные. Статическому внутреннему классу, напротив, недоступны какие-либо методы или переменные внешнего класса.

Где в памяти Java хранятся статические классы и переменные?

Вплоть до 8-й версии Java статические методы и переменные хранились в пространстве permgen. Но потом было введено новое пространство памяти, называемое метапространством — в нем хранятся все эти имена и поля класса, методы класса с байт-кодом методов, пул констант, JIT-оптимизации и т. д. Причина удаления permgen в Java 8.0 в том, что очень сложно предсказать необходимый размер permgen.

Зачем нужно ключевое слово final?

Что такое конечная переменная и когда ей стоит воспользоваться?

Существует три способа инициализации конечной переменной.

Когда следует применять конечную переменную

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

Где использовать конечные классы

При попытке расширить конечный класс компилятор выдаст следующее исключение:

Для чего в java статические блоки. Смотреть фото Для чего в java статические блоки. Смотреть картинку Для чего в java статические блоки. Картинка про Для чего в java статические блоки. Фото Для чего в java статические блоки

Когда использовать конечные методы

Здесь происходит попытка переопределить метод final из родительского класса. Java этого не позволяет и выдает следующее исключение:

Для чего в java статические блоки. Смотреть фото Для чего в java статические блоки. Смотреть картинку Для чего в java статические блоки. Картинка про Для чего в java статические блоки. Фото Для чего в java статические блоки

Источник

Руководство по статическому ключевому слову в Java

Узнайте о статических полях Java, статических методах, статических блоках и статических внутренних классах.

1. введение

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

2. Анатомия статического ключевого слова

В языке программирования Java ключевое слово static указывает, что конкретный член принадлежит самому типу, а не экземпляру этого типа .

Это означает, что создается только один экземпляр этого статического члена, который является общим для всех экземпляров класса.

Ключевое слово может быть применено к переменным, методам, блокам и вложенному классу.

3. Статические Поля (Или Переменные Класса)

С точки зрения памяти статические переменные попадают в определенный пул в памяти JVM, называемый Metaspace (до Java 8 этот пул назывался Permanent Generation или PermGen, который был полностью удален и заменен Metaspace).

3.1. Пример статического поля

Предположим, у нас есть класс Car с несколькими атрибутами (переменными экземпляра) . Всякий раз, когда новые объекты инициализируются из этого Car blueprint, каждый новый объект будет иметь свою отдельную копию этих переменных экземпляра.

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

Вот тут-то и появляются статические переменные:

3.2. Веские причины для использования статических полей

3.3. Ключевые моменты, которые необходимо запомнить

4. Статические Методы (Или Методы Класса)

Подобно static полям, static методы также принадлежат классу, а не объекту, и поэтому их можно вызывать без создания объекта класса, в котором они находятся. Они предназначены для использования без создания объектов класса.

4.1. Пример статического метода

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

Если есть код, который должен быть общим для всех экземпляров этого класса, напишите этот код в статическом методе:

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

4.2. Веские причины для использования статических методов

4.3. Ключевые моменты, которые следует запомнить

5. Статический Блок

В таких случаях пригодятся статические блоки.

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

5.1. Пример статического Блока

Предположим, мы хотим инициализировать объект списка с некоторыми заранее определенными значениями.

Это становится легко с статическими блоками:

5.2. Веские причины для использования статических блоков

5.3. Ключевые моменты, которые необходимо запомнить

6. Статический класс

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

Архитектура вложенного класса разделена на две части:

Основное различие между этими двумя классами заключается в том, что внутренние классы имеют доступ ко всем членам заключающего класса (включая private), в то время как статические вложенные классы имеют доступ только к статическим членам внешнего класса.

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

6.1. Пример статического класса

Наиболее широко используемый подход к созданию одноэлементных объектов-это статический вложенный класс, он не требует никакой синхронизации и прост в освоении и реализации:

6.2. Веские причины для использования статического внутреннего класса

6.3. Ключевые моменты, которые следует запомнить

7. Заключение

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

Источник

Блоки статической и объектной инициализации

Давайте начнем со следующего примера. Программа SmallSquares (маленькие квадраты) возвращает квадрат маленького целого числа. SmallSquares имеет 2 статические переменные и единственную открытую статическую функцию getSquare().

public class SmallSquares <

private static final int LIMIT = 10 ;
private static final int [] square = new int [ LIMIT ] ;

public SmallSquares () < // не пишите такой код
for ( int i = 0 ; i ) <
square [ i ] = i * i;
>
>
>
public static int getSquare ( int i ) <
// Нет обработки ошибки, предположим, 0 return square [ i ] ;
>

public static void main ( String [] args ) <
new SmallSquares () ;
System.out.println ( «3 squared is » +
getSquare ( 3 )) ;
>
>

Откомпилируйте и запустите SmallSquares, вы должны получить следующий результат:

Как вы наверное догадались из комментария программы, это действительно плохой код. Мы игнорируем недостаток границ проверки аргумента getSquare(). Также игнорируем тот факт, что индексация в очереди чуть ли не дороже, чем простое возведение в квадрат числа. Отложим эти факты в сторону, сконцентрируемся на неэкономном создании объекта, называемом статическим методом.

А ещё лучше использовать статическую инициализацию. За словом статический (static) следует блок кода, окруженного фигурными скобками. Вы можете использовать статический блок для инициализации массива квадратов вот так:

Поставьте этот блок в код программы SmallSquare после объявления квадрата. Из-за статичности блок запрашивается единожды, когда создается класс. Теперь вам не нужен конструктор, и вы можете вызывать статическую функцию getSquare() без предшествующего создания класса. Вот улучшенный код:

public class SmallSquares <

private static final int LIMIT = 10 ;
private static final int [] square = new int [ LIMIT ] ;

static <
for ( int i = 0 ; i ) <
square [ i ] = i * i;
>
>

public static int getSquare ( int i ) <
// Нет обработки ошибки, предположим,0 return square [ i ] ;
>

public static void main ( String [] args ) <
System.out.println ( «3 squared is » + getSquare ( 3 )) ;
>
>

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

public class ConstructorExample <
private final String userName;
private final static int [] square = new int [ 10 ] ;

public ConstructorExample () < // так не следует писать
this ( «Anonymous» ) ;
>

Откомпилируйте и запустите ConstructorExample. Вы должны получить следующий результат:

Пример конструктора можно привести в порядок, переместив поле инициализатора для имени пользователя (userName) и введя следующий блок инициализатора:

Данный блок инициализаторов выглядит как блок статического инициализатора без статического ключевого слова. Он запускается перед тем, как вызвать конструктор. Это значит, что вначале квадрат инициализируется не правильно в зависимости от того, вызывает ли пользователь конструктор без аргумента или использует сигнатуру, требующую строку (String). Отметить, что если у вас есть другой конструктор, который устанавливает размер массива, вы не сможете применять этот метод. Потому что данный инициализатор будет вызван, чтобы инициализировать квадрат, перед тем, как будет прочитан размер массива.

Вы можете разделить конструкторы в примере (ConstructorExample), передвинув следующие строки от конструктора без аргумента:

В следующей программе появляется пустой конструктор, ConstructorExample2 (пример конструктора 2), чтобы продемонстрировать введение данного блока инициализации.

public class ConstructorExample2 <

private final String userName;
private static final int [] square = new int [ 10 ] ;
<
for ( int i = 0 ; i 10 ; i++ ) <
square [ i ] = i * i;
>
>

public ConstructorExample2 () <
userName = «Anonymous» ;
>

public void printSquare ( int i ) <
// Нет обработки ошибки, предположим,0 System.out.println ( «Hello » + userName ) ;
System.out.println ( i + » squared is » + square [ i ]) ;
>

В примере AnonymousExample используется функция createAnonSquare(). Эта функция создает безымянный внутренний класс, который распространяется на AnonymousSquare (безымянный квадрат). Этот пример не более чем инициализация переменных userName и Ed.

Безымянный класс наследует квадрат и функцию print(). Это значит, что вы можете создавать AnonymousSquare (Безымянный квадрат) и вызывать print(). Вы должны получить «Hi Ed, 3 squared is 9.» (Привет Эд, 3 в квадрате будет 9).

static class AnonymousSquare
private static final int [] square = new int [ 10 ] ;

<
for ( int i = 0 ; i 10 ; i++ )
square [ i ] = i * i;
>

String userName;
int i;

void print () <
System.out.println ( «Hi » + userName + «, » + i
+ » squared is » + square [ i ] + ‘.’
) ;
>
>

static AnonymousSquare createAnonSquare () <
return new AnonymousSquare () <
<
userName = «Ed» ;
i = 3 ;
>
> ;
>

Однажды, попробовав работать с блоками инициализации, вы возможно найдёте для них много приложений. Данные инициализаторы лучше всего подходят к безымянным внутренним классам и не часто используются в обычных Java-классах. Вы убедитесь, что статические инициализаторы очень удобные.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *