User Petr Gorskin
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В завершение хочу сказать, что написание этой статьи явилось реализацией моего желания изучить модификаторы. Успешный опыт или нет — на ваш суд. Я жду ваших предложений по ее улучшению/исправлению и, возможно совместно мы сделаем из нее полезнейший мануал для начинающих джавистов.
Комментарии (33)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Андрей Овчаренко Уровень 41, Москва
6 февраля 2021
Но позвольте, опечатка в финальной картинке - пятая красная строка, первый столбец. Статическая переменная НЕ уникальна для всех экземпляров класса
AlinaAlina Уровень 35, Санкт-Петербург
12 мая 2020
А ещё... Поскольку статические поля класса не сериализуются, не имеет смысла одновременное использование модификаторов static и transient. Тем не менее, компилятор полагает такое сочетание корректным. Подробнее: http://cyclowiki.org/wiki/Transient_(Java)
дима чабай Уровень 0
9 февраля 2020
Еще private abstract нельзя вместе использовать
Игорь Сторожук Уровень 22, Москва, Россия
19 января 2020
volatile, final, abstract, static и пр. пишутся со строчной буквы
Владимир Плеханов Уровень 27, Самара, Россия
26 декабря 2019
Классно , но немного покоробило слово "уникальна" в шпаргалке про static. Как- будто слово не совсем то. Уникальное поле как раз не статик. А вот статик у всех едино. Поправьте, если неправ...
Mykola Уровень 26, Helsinki
22 декабря 2019
Спасибо! Шпаргалку сохранил!
Семён Уровень 41, Красногорск, СССР
20 ноября 2019
К сожалению, не раскрыта тема, что модификаторы принято вызывать в определенном порядке: 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
Юля Лобас Уровень 26, Костанай, Казахстан
22 октября 2019
В общем мне понравилось))) Лайк)
Валентин Кудинов Уровень 41, Самара, Россия
24 сентября 2019
Норм.
Василий Самарин Уровень 27, Санкт-Петербург, Россия
2 сентября 2019
Хорошая статья, только небольшая неточность, на мой взгляд, где написано про static: "Статические методы могут быть вызваны без создания класса". Правильный вариант: "Статические методы могут быть вызваны без создания объекта".