Автор: Widowmaker1984

Вопрос 80-89 (модификаторы)

"Можно ли получить доступ к private переменным класса и если да, то каким образом?"
"Модификаторы. Назначение и варианты использования."
"Что такое volatile и transient?"
"Контексты использования модификаторов (класс/поле/метод)."
"Какой из модификаторов более строгий: protected или package-private?"
"Расширение модификаторов при наследовании, переопределение и сокрытие методов. Если у класса-родителя есть метод, объявленный как private, может ли наследник расширить его видимость? А если protected? А сузить видимость?"
"Модификатор abstract и final для классов/методов."
"Имеет ли смысл объявлять метод private final?"
"Какие особенности инициализации final переменных?"
"Что будет, если единственный конструктор класса объявлен как final?"


1. Модификаторы — ключевые слова, которые добавляются при инициализации для изменения значений. Язык Java имеет широкий спектр модификаторов, основные из них:
- модификаторы доступа;
- модификаторы класса, метода, переменной и потока, используемые не для доступа.

скрытый текст2. В Java существуют следующие модификаторы доступа:
- private: члены класса доступны только внутри класса;
- default (package-private) (модификатор, по-умолчанию): члены класса видны внутри пакета (если класс будет так объявлен он будет доступен только внутри пакета);
- protected: члены класса доступны внутри пакета и в наследниках;
- public: члены класс доступны всем;

2.1. Последовательность модификаторов по убыванию уровня закрытости: private, default, protected, public.

2.2. Доступ к полям модификатором доступа private рекомендуется осуществлять через специальные методы с заголовками, начинающимися с get/set.

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

2.3. Во время наследования возможно изменения модификаторов доступа в сторону большей видимости. Так сделано для того, чтобы не нарушался принцип LSP («подкласс не должен требовать от вызывающего кода больше, чем базовый класс, и не должен предоставлять вызывающему коду меньше, чем базовый класс») для наследуемого класса.

2.3.1. Поэтому методы, объявленные как public в суперклассе, также должны быть public во всех подклассах. Методы, объявленные как protected в суперклассе, должны либо быть либо protected, либо public в подклассах; они не могут быть private. Методы, объявленные как private для всех не наследуются, так что нет никакого правила для них.

3. Java предоставляет ряд модификаторов не для доступа, а для реализации многих других функциональных возможностей:
- модификатор static применяется для создания статических методов и переменных класса;
- модификатор final используется для завершения реализации классов, методов и переменных;
- модификатор abstract необходим для создания абстрактных классов и методов;
- модификаторы synchronized и volatile используются в Java для потоков;
- прочие модификаторы (strictfp, transient, native).

3.1. Модификатор synchronized применяется только к методам и их частям. Указывает, что метод может быть доступен только одному потоку одновременно. В Java модификатор synchronized может быть применен с любым из четырех модификаторов уровня доступа.

3.2. Модификатор transient: переменная экземпляра отмеченная как transient указывает виртуальной машине Java (JVM пропустить эту переменную при сериализации содержащего её объекта.

3.2.1. Применяется только для переменных уровня класса (локальные переменные не могут быть объявлены как transient). Transient переменные могут не быть final или static.

3.3. Модификатор volatile используется, чтобы указать JVM, что при обращении к полю не используется кэш (имеется ввиду область памяти в которой JVM может сохранять локальную копию переменной, чтобы уменьшить время обращения к переменной). Для volatile переменной JVM гарантирует синхронизацию для операций чтения/записи, но не гарантирует для операций изменения значения переменной.

3.3.1. Модификатор применим только к переменным экземпляра, которые имеют тип объект или private. Ссылка на объект с модификатором volatile может быть null.

3.3.2. Может использоваться со static переменными. Не используется с final переменными.

3.4. Модификатор strictfp применяется для методов и классов. Обеспечивает выполнение операций над числами типа float и double (с плавающей запятой) по стандарту IEEE 754.

3.5. Модификатор native используется только для методов. Обозначает, что метод написан на другом языке программирования. Классы в Java используют native методы для повышения производительности и доступа к аппаратным средствам Можно предавать и возвращать Java объекты из native методов. Сигнатура метода должна заканчиваться “;”, фигурные скобки вызовут ошибку компиляции.

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

4.1.1. С переменными модификатор final часто используется совместно со static, чтобы сделать переменную класса константой. Подобные переменные должны быть инициализированы во время объявления или в статическом блоке.

4.2. Метод с final не может быть переопределен. Аргументы методов, обозначенные как final, предназначены только для чтения, при попытке изменения будет ошибка компиляции.

4.2.1. Абстрактный класс не может создать экземпляр. Если класс объявлен как abstract, то единственная цель для него быть расширенным через наследование. Класс не может быть одновременно abstract и final, так как класс с модификатором final не может быть расширенным.

4.3. От класса с final нельзя наследоваться. Поэтому все его методы не могут быть переопределены и неявно также становятся финальными.

4.3.1. Абстрактный метод является методом, объявленным без реализации (без тела метода). Методы abstract никогда не могут быть final.

5. "Суперпункт" для разбора частных вопросов.

5.1. "Имеет ли смысл объявлять метод private final?" Модификатор final позволяет заблокировать метод от переопределения в классах наследниках. Однако private методы и так недоступны в классах наследниках, поэтому перепределить такие методы там нельзя и дополнительный модификатор final не окажет никакого влияния. Можно сказать, что private методы и так неявно являются final методами.

5.2. "Что будет, если единственный конструктор класса объявлен как final?" Конструктор не может иметь подобного модификатора.

6. Таблица с возможностью применить модификаторы в том или ином контексте:
http://www.quizful.net/post/features-of-the-application-of-modifiers-in-java

6.1. Классы (включая любые вложенные классы) могут быть default и strictfp. За исключением анонимных они могут быть abstract или final. Вложенные за исключением локальных (включая анонимные) могут иметь модификатор доступа (верхнего уровня — только public). И только вложенные классы могут быть static.

6.2. Методы в общем случае могут использовать все модификаторы за исключением специально предназначенных для переменных transient и volatile. Конструкторы в отличие от методов не может иметь модификаторов abstract, final, native, static или synchronized.

6.3. Переменные в общем случае могут использовать все модификаторы за исключением не имеющих для них смысла abstract, native и strictfp.

6.4. Логический блок может иметь модификаторы default, static и (как часть метода) synchronized.

Комментарии


Лучшее   Правила сайта   Вход   Регистрация   Восстановление пароля

Материалы сайта предназначены для лиц старше 16 лет (16+)