JavaRush/Java блог/Random/Модификаторы или как накладывать чары в мире Java
Petr Gorskin
22 уровень

Модификаторы или как накладывать чары в мире Java

Статья из группы Random
участников
Доброго галактического времени суток, комрады! Это мой первый межпланетный манускрипт, а поскольку являюсь я инженером, трактовка некоторых понятий может производиться на внеземном языке.
Модификаторы или как накладывать чары в мире Java - 1
Вступление На мой взгляд Java похожа на бесконечный коридор с дверьми (package). За каждой из таких дверей имеется свободное пространство и картотека, в которой хранится гора магических свитков с инструкциями (классов) по созданию объектов. В каждом свитке описывается набор характеристик (переменных) и способностей (методов) — действий (полей), совершаемых над или самим классом, или собранным на его основе объектом. На этом этапе давайте представим себя волшебниками и попробуем создать совершенно новую инструкцию (класс). Итак: Модификаторы или как накладывать чары в мире Java - 2Выпиваем эликсир мудрости (изучаем основы) и приступаем к написанию инструкции. Access и non-access модификаторы Представим себе, что любая инструкция и создаваемый на ее основе объект, а также его характеристики и способности будут изначально магически зачарованы, т.е. им будут присвоены определенные наборы модификаторов. Попробуем создать пособие по возможным зачарованиям.
  1. Модификатор доступа, который описывает доступность класса, объекта или поля — обязательный: при его отсутствии JVM (это такой источник вселенской магии) автоматически присваивает идентификатор по умолчанию package.

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

  2. Модификатор Static говорит о том, что класс, объект или поле статичны. Но что это значит? В основном он примерим к полям.

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

  3. Модификатор Final фактически служит для переменной указанием на то, что она является константой. Для методов — что они не могут быть переопределены при наследовании, ну а для классов это указание на то, что наследоваться от него нельзя (immutable).

    Модификаторы static и final применимы к классам, объектам и полям. Однако есть модификаторы, которые применимы лишь к некоторым из них (или даже части, ведь и переменная и метод — это поле, но не все модификаторы применимы к обоим). Если проводить аналогию, на скорость можно зачаровать лишь ботинки и перчатки (чтобы быстрее двигались), а вот зачаровывать шляпу на скорость бессмысленно (да и Вселенский Надзирательный Совет (компилятор) не даст).

  4. Модификатор Abstract применим только к методам и классам. Абстрактный метод — это метод без реализации (тела).

    Если класс помечается как абстрактный, он либо содержит абстрактные методы, либо это делается для того чтобы запретить создание экземпляров этого класса. Если проводить аналогию, посреди инструкции можно увидеть заголовок «Раскраска объекта», после которого нет описания. Т.е. по этой инструкции можно создать объект и раскрасить его тоже можно, но в конкретно этой инструкции не написано как (пишите свою инструкцию по созданию красного объекта на основе этого объекта и опишите как его раскрашивать).

При работе в многопоточной среде могут использоваться специальные модификаторы:
  1. Модификатор Syncronized используется только для методов. Его наличие свидетельствует о том, что его может одновременно выполнять лишь один поток. Также может использоваться в виде отдельного блока кода внутри объекта (с указанием объекта синхронизации).

  2. Модификатор Volatileтолько для переменных. Его рекомендуется использовать для переменных, которые могут быть одновременно использоваться несколькими потоками. Переменная с таким модификатором при каждом изменении моментально копируется из кэша процессора в основную память, позволяя параллельным потокам получать самое «свежее» значение.

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

  3. Модификатор Transientтолько для переменных. Таким модификатором помечаются переменные, которые нужно пропускать при сериализации объекта (это такой умный процесс, о котором, в принципе, и самостоятельно почитать можно…)*

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

Конфликтующие пары модификаторов Помимо применимости модификаторов к различным классам, объектам и полям существует также понятие конфликтующих пар. Допустим, наложение на шлем чар прочности делает его тяжелым, и одновременно вы хотите зачаровать его на легкость. Одно с другим не вяжется.
  1. Final и Volatile – когда речь идет о переменных, мы не можем одновременно сказать что она финальна (константа) и что несколько потоков имеют возможность ее изменить… Ведь она постоянна, и в любой момент поток может ее считать, но ни один поток не в силах изменить константу (Вселенский Надзирательный Совет не даст).
  2. Final и Abstract — классы и методы не могут быть одновременно абстрактными (что в большинстве случаев подразумевает необходимость их уточнения для реализации) и финальными, т.е. неизменяемыми. Получается, что в инструкции написано, как создать хороший прочный шлем из любого материала (абстрактная часть), но для этого в нем обязательно не должно быть отверстий (финальная обязательная часть, изменению не подлежит).
  3. Abstract и Static — абстрактный метод не может одновременно быть статическим или синхронизированным. Статический абстрактный метод не имеет смысла, ведь он мало того, что ничего не делает, так еще и принадлежит целому классу — бесполезная штука получается.
  4. Abstract и Syncronized — какой смысл в синхронизации работы с методом, который ничего не делает?
Подведение итогов Итак, описание модификаторов закончилось, все конфликты разобраны и теперь можно закрепить полученный результат шпаргалкой — схемой зачарований: Модификаторы или как накладывать чары в мире Java - 3В завершение хочу сказать, что написание этой статьи явилось реализацией моего желания изучить модификаторы. Успешный опыт или нет — на ваш суд. Я жду ваших предложений по ее улучшению/исправлению и, возможно совместно мы сделаем из нее полезнейший мануал для начинающих джавистов.
Комментарии (38)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Para Ino
Уровень 41
9 января 2023, 10:45
10 очков гриффиндору!)
marych
Уровень 51
22 июля 2022, 14:06
Отличный материал
Мирослав
Уровень 29
Expert
8 мая 2022, 12:47
Вполне внятное объясненье! Спасибо!
6 февраля 2021, 13:59
Но позвольте, опечатка в финальной картинке - пятая красная строка, первый столбец. Статическая переменная НЕ уникальна для всех экземпляров класса
Anonymous #2497267
Уровень 2
15 апреля 2021, 08:44
А, какая же она по вашему ?
Alexey
Уровень 4
3 ноября 2022, 19:13
Она единая для всех экземпляров. Например в нее можно засунуть счетчик объектов. Он будет общий для всех. Засунуть "счетчик++;" в конструктор и он будет увеличиваться с каждым созданием объекта. То есть переменная не_уникальна для каждого экземпляра, а общая.
AlinaAlina
Уровень 35
12 мая 2020, 18:10
А ещё... Поскольку статические поля класса не сериализуются, не имеет смысла одновременное использование модификаторов static и transient. Тем не менее, компилятор полагает такое сочетание корректным. Подробнее: http://cyclowiki.org/wiki/Transient_(Java)
Игорь Сторожук
Уровень 22
19 января 2020, 11:59
volatile, final, abstract, static и пр. пишутся со строчной буквы
26 декабря 2019, 13:13
Классно , но немного покоробило слово "уникальна" в шпаргалке про static. Как- будто слово не совсем то. Уникальное поле как раз не статик. А вот статик у всех едино. Поправьте, если неправ...
Denis Sidorenko Java Developer в СберТех
14 февраля 2020, 06:16
не то чтобы едино))) а статик у всех "один такой на всех" = "уникальный";
Mykola
Уровень 26
22 декабря 2019, 20:52
Спасибо! Шпаргалку сохранил!
Семён
Уровень 41
20 ноября 2019, 17:39
К сожалению, не раскрыта тема, что модификаторы принято вызывать в определенном порядке: 1.public 2.protected 3.private 4.abstract 5.default 6.static 7.final 8.transient 9.volatile 10.synchronized 11.native 12.strictfp Понятно, что не все одновременно, но если их несколько, то желательно, чтобы такой порядок соблюдался. Подробнее разжёвано здесь, как и многие другие вещи, рекомендую: https://www.youtube.com/watch?v=XcWqkNE3dzE&list=PLrCZzMib1e9pz7f30YqoBLY0_AfiC36kM
Gans Electro
Уровень 50
20 апреля 2023, 05:02
1.public ||
2.protected ||
3.private ||

4.abstract ||    (!&& (static || final || synchronized))
5.default ||

6.static    (!&& abstract)
7.final    (!&& (abstract || volatile))

8.transient
9.volatile (!&& final)

10.synchronized    (!&& abstract)

11.native
12.strictfp

|| - знак или. Не могут быть поля или методы у которого
(Например: public private void method()) они стоят подряд
!&& - знак не могут быть в паре.

Что скажете о строке:
private default static transient volatile void method()
{System.out.println("The World!")}

ChatGPT:
1. В классе:
public
protected
private
abstract
static
final
default
strictfp

2. В методе:
public
protected
private
abstract
static
final
default
strictfp

synchronized
native

3. В полях:
public
protected
private
static
final
transient
volatile

4. В переменных:
final
transient
volatile

5. В других местах в коде:
synchronized
native

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

В параметрах методов.
В аргументах конструкторов.
В объявлении исключений методов.
В типах параметров и возвращаемых значений методов.
В лямбда-выражениях.
В статических инициализаторах блоков.
В аннотациях и многое другое.
Юля Лобас Ведущий Инженер программи в Костанайский ЭнергоЦ
22 октября 2019, 16:32
В общем мне понравилось))) Лайк)