что такое private static в java
3 ответа 3
Посмотрите данные по шаблону проектирования singleton.
private static гарантирует единственность экземпляра объекта с такими свойствами в потоке, где задействован класс.
private static final гарантирует, что этот экземпляр не подменится на что-то другое.
Удобно при работе с базами данных или каким-то ресурсом, не склонным к разделению.
Какой толк от static, если он помечен как private?
Необходимо, если переменную нужно использовать в статических методах
Final нужно использовать, если ссылка будет инициализироваться один раз и не должна быть заменена. В большинстве случаев static переменные именно так и используются.
Модификаторы доступа static final следует применять, когда есть необходимость явно указать на то, что переменную не следует или запрещено изменять, то есть модификаторы static final превращают переменную в константу.
В свою очередь переменные помеченные модификатором static являются обычными переменными с тем лишь различием, что их экземпляр (в единственном числе) хранится не с экземпляром каждого создаваемого объекта (области памяти где хранятся переменные экземпляра), а в объекте который описывает ваш класс при этом на каждой JVM такой объект существует в единственном экземпляре. С переменными объявленными как static можно делать все то же что и с обычными переменными при этом для доступа к таким переменным ненужно (но можно получить доступ и через переменную экземпляра) создавать экземпляр класса (конечно если переменная имеет модификатор доступа public ), например, создадим класс содержащий статическую переменную:
Получение подступа к статической переменной:
Присваиваем новое значение статической переменной:
Такие переменные следует применять, когда есть необходимость иметь одну переменную на все экземпляры классов или если необходимо использовать переменную в статическом методе (переменные экземпляра в таком методе недоступны так как экземпляров класса может вообще не существовать на момент вызова статического метода).
При использовании модификатора private свойства переменной и «константы» не изменяются, изменяется лишь доступность переменной/константы.
8. Java — Модификаторы доступа и класса
Модификаторы — ключевые слова, которые Вы добавляете при инициализации для изменения значений. Язык Java имеет широкий спектр модификаторов, основные из них:
Чтобы использовать модификатор в Java, нужно включить его ключевое слово в определение класса, метода или переменной. Модификатор должен быть впереди остальной части оператора, как показано в следующих примерах:
Содержание
Модификаторы доступа
Java предоставляет ряд модификаторов доступа, чтобы задать уровни доступа для классов, переменных, методов и конструкторов. Существует четыре доступа:
Модификатор доступа по умолчанию — без ключевого слова
Модификатор доступа по умолчанию — означает, что мы явно не объявляем модификатор доступа в Java для класса, поля, метода и т.д.
Переменная или метод, объявленные без модификатора контроля доступа доступны для любого другого класса в том же пакете. Поля в интерфейсе неявно являются public, static, final, а методы в интерфейсе по умолчанию являются public.
Пример
Переменные и методы могут быть объявлены в Java без каких-либо модификаторов, как показано в следующем примере:
Модификатор доступа private
Модификатор private — методы, переменные и конструкторы, которые объявлены как private в Java могут быть доступны только в пределах самого объявленного класса.
Модификатор доступа private является наиболее ограничивающим уровенем доступа. Класс и интерфейсы не могут быть private.
Переменные, объявленные как private, могут быть доступны вне класса, если получающие их открытые (public) методы присутствуют в классе (ниже смотрите пример и пояснения).
Использование модификатора private в Java является основным способом, чтобы скрыть данные.
Пример
Следующий класс использует контроль доступа private:
Здесь переменная format класса Logger является private, так что нет никакого способа для других классов, чтобы получить и установить её значение напрямую.
Таким образом, чтобы эта переменная была доступна для всего, мы определили два открытых (public) метода: getFormat(), который возвращает значение format, и setFormat(String), который устанавливает её значение.
Модификатор доступа public
Модификатор public — класс, метод, конструктор, интерфейс и т.д. объявленные как public могут быть доступны из любого другого класса. Поэтому поля, методы, блоки, объявленные внутри public класса могут быть доступны из любого класса, принадлежащего к «вселенной» Java.
Тем не менее, если к public классу в другом пакете мы пытаемся получить доступ, то public класс приходится импортировать.
Благодаря наследованию классов, в Java все публичные (public) методы и переменные класса наследуются его подклассами.
Пример
Следующая функция использует контроль доступа public:
Метод main() должен быть публичным (public). В противном случае, он не может быть вызван с помощью java-интерпретатора, чтобы запустить класс.
Модификатор доступа protected
Модификатор protected — переменные, методы и конструкторы, которые объявляются как protected в суперклассе, могут быть доступны только для подклассов в другом пакете или для любого класса в пакете класса protected.
Модификатор доступа protected в Java не может быть применен к классу и интерфейсам. Методы и поля могут быть объявлены как protected, однако методы и поля в интерфейсе не могут быть объявлены как protected.
Доступ protected дает подклассу возможность использовать вспомогательный метод или переменную, предотвращая неродственный класс от попыток использовать их.
Пример
Следующий родительский класс использует контроля доступа protected, чтобы его дочерний класс переопределил метод openSpeaker():
При этом, если мы определим метод openSpeaker() как protected, то он не будет доступен из любого другого класса, кроме AudioPlayer. Если мы определим его как public, то он станет доступным всем. Но наше намерение состоит в том, чтобы раскрыть этот метод только подклассу, вот почему мы использовали модификатор protected.
Правила контроля доступа и наследования
Следующие правила в Java применяются для унаследованных методов:
Модификаторы класса, метода, переменной и потока, используемые не для доступа
Java предоставляет ряд модификаторов не для доступа, а для реализации многих других функциональных возможностей:
Модификатор static
Модификатор static — применяется для создания методов и переменных класса.
Переменные static
Ключевое слово static используется для создания переменных, которые будут существовать независимо от каких-либо экземпляров, созданных для класса. Только одна копия переменной static в Java существует вне зависимости от количества экземпляров класса.
Статические переменные также известны как переменные класса. В Java локальные переменные не могут быть объявлены статическими (static).
Методы static
Ключевое слово static используется для создания методов, которые будут существовать независимо от каких-либо экземпляров, созданных для класса.
В Java статические методы или методы static не используют какие-либо переменные экземпляра любого объекта класса, они определены. Методы static принимают все данные из параметров и что-то из этих параметров вычисляется без ссылки на переменные.
Переменные и методы класса могут быть доступны с использованием имени класса, за которым следует точка и имя переменной или метода.
Пример
Модификатор static в Java используется для создания методов классов и переменных, как показано в следующем примере:
Будет получен следующий результат:
Модификатор final
Модификатор final — используется для завершения реализации классов, методов и переменных.
Переменные final
Переменная final может быть инициализирована только один раз. Ссылочная переменная, объявленная как final, никогда не может быть назначен для обозначения другого объекта.
Однако данные внутри объекта могут быть изменены. Таким образом, состояние объекта может быть изменено, но не ссылки.
С переменными в Java модификатор final часто используется со static, чтобы сделать константой переменную класса.
Пример
Методы final
Метод final не может быть переопределен любым подклассом. Как упоминалось ранее, в Java модификатор final предотвращает метод от изменений в подклассе.
Главным намерение сделать метод final будет то, что содержание метода не должно быть изменено стороне.
Пример
Объявление метода, использующего модификатор final в объявление класса, показано в следующем примере:
Класс final
Основная цель в Java использования класса объявленного в качестве final заключается в предотвращении класс от быть подклассом. Если класс помечается как final, то ни один класс не может наследовать любую функцию из класса final.
Пример
Модификатор abstract
Модификатор abstract — используется для создания абстрактных классов и методов.
Класс abstract
Класс abstract не может создать экземпляр. Если класс объявлен как abstract, то единственная цель для него быть расширенным.
Класс не может быть одновременно abstract и final, так как класс final не может быть расширенным. Если класс содержит абстрактные методы, то он должен быть объявлен как abstract. В противном случае будет сгенерирована ошибка компиляции.
Класс abstract может содержать как абстрактные методы, а также и обычные.
Пример
Метод abstract
Метод abstract является методом, объявленным с любой реализацией. Тело метода (реализация) обеспечивается подклассом. Методы abstract никогда не могут быть final или strict.
Любой класс, который расширяет абстрактный класс должен реализовать все абстрактные методы суперкласса, если подкласс не является абстрактным классом.
Если класс в Java содержит один или несколько абстрактных методов, то класс должен быть объявлен как abstract. Абстрактный класс не обязан содержать абстрактные методы.
Абстрактный метод заканчивается точкой с запятой. Пример: public abstract sample();
Пример
Модификатор synchronized
Модификатор synchronized — используются в Java для потоков.
Ключевое слово synchronized используется для указания того, что метод может быть доступен только одним потоком одновременно. В Java модификатор synchronized может быть применен с любым из четырех модификаторов уровня доступа.
Пример
Модификатор transient
Переменная экземпляра отмеченная как transient указывает виртуальной машине Java (JVM), чтобы пропустить определённую переменную при сериализации объекта, содержащего её.
Этот модификатор включён в оператор, что создает переменную, предшествующего класса или типа данных переменной.
Пример
Модификатор volatile
Модификатор volatile — используются в Java для потоков.
В Java модификатор volatile используется, чтобы позволить знать JVM, что поток доступа к переменной всегда должен объединять свою собственную копию переменной с главной копией в памяти.
Доступ к переменной volatile синхронизирует все кэшированные скопированные переменные в оперативной памяти. Volatile может быть применен только к переменным экземпляра, которые имеют тип объект или private. Ссылка на объект volatile может быть null.
Пример
Как правило, run() вызывается в одном потоке (впервые начинаете использовать Runnable в Java), а stop() вызывается из другого потока. Если в линии 1 используется кэшированное значение active, то цикл не может остановиться, пока Вы не установите active false в линии 2.
В следующем уроке обсудим основные операторы, используемые в языке 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. Я надеюсь, что каждый разработчик доведёт свои навыки использования статических концептов до совершенства, т.к. это очень важно для серьёзного программирования.»
Статические переменные
1. Статические переменные
Когда класс загружается в память, для него сразу создается статический объект класса. Этот объект хранит статические переменные класса (статические поля класса). Статический объект класса существует, даже если не был создан ни один обычный объект класса.
Когда мы описываем переменные в классе, мы указываем, будут ли эти переменные созданы всего один раз или же нужно создавать их копии для каждого объекта. По умолчанию создаётся новая копия переменной для каждого объекта.
Статическая (static) же переменная привязана к статическому объекту класса и всегда существует в единственном экземпляре.
Если статической переменной не присвоить стартовое значение, она инициализируется значением по умолчанию:
Тип | Значение по умолчанию |
---|---|
(то же самое, что и ) | |
и любые классы |
Обращаться к статической переменной в ее классе можно просто по имени. Если обращение идет из другого класса, то перед именем статической переменной нужно писать имя класса.
2. Отличие статических и нестатических переменных
Чем же отличаются обычные и статические переменные?
Обычные переменные класса привязаны к объектам своего класса (экземплярам класса), статические переменные — к статическому объекту класса.
Если экземпляров класса несколько, в каждом из них существует своя копия нестатических (обычных) переменных класса. Статические переменные класса всегда находятся внутри статического объекта класса и существуют только в одном экземпляре.
Обращаться к обычным переменным класса (полям класса) можно только имея ссылку на объект класса. Ну или в методах внутри этого же класса.
Обращение к полю класса с использованием ссылки на объект класса |
---|
Обращаться к статическим переменным можно откуда угодно (с учетом модификаторов видимости): из обычных методов, из статических методов того же класса, из методов других классов и т.п.
Обращение к статическому полю класса не используя ссылку на объект класса |
---|
Устройство в памяти:
Допустим, у нас есть класс Person с 4 полями: два статических, а два — нет.
Сразу после загрузки класса
После создания первого объекта
Обратите внимание, что хоть у объектов по две переменные, это разные переменные: у обычного объекта — обычные, у статического — статические.
Нужно больше объектов
Обратите внимание: у каждого объекта есть собственная переменная age и name.
Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 15
Java Core
9. В чем разница между статическим и динамическим связыванием в Java?
10. Можно ли использовать private или protected переменные в interface?
11. Что такое Classloader и для чего используется?
Bootstrap ClassLoader — базовый загрузчик, реализован на уровне JVM и не имеет обратной связи со средой выполнения, так как является частью ядра JVM и написан в машинном коде. Данный загрузчик служит родительским элементом для всех других экземпляров ClassLoader.
В основном отвечает за загрузку внутренних классов JDK, обычно rt.jar и других основных библиотек, расположенных в каталоге $ JAVA_HOME / jre / lib. У разных платформ могут быть разные реализации этого загрузчика классов.
Extension Classloader — загрузчик расширений, потомок класса базового загрузчика. Заботится о загрузке расширения стандартных базовых классов Java. Загружается из каталога расширений JDK, обычно — $ JAVA_HOME / lib / ext или любого другого каталога, упомянутого в системном свойстве java.ext.dirs (с помощью данной опции можно управлять загрузкой расширений).
System ClassLoader — системный загрузчик, реализованный на уровне JRE, который заботится о загрузке всех классов уровня приложения в JVM. Он загружает файлы, найденные в переменном окружении классов -classpath или -cp опции командной строки.
System Classloader пытается найти класс в своем кеше.
1.1. Если класс найден, загрузка успешно завершена.
1.2. Если класс не найден, загрузка делегируется к Extension Classloader-у.
Extension Classloader пытается найти класс в собственном кеше.
2.1. Если класс найден — успешно завершена.
2.2. Если класс не найден, загрузка делегируется Bootstrap Classloader-у.
Bootstrap Classloader пытается найти класс в собственном кеше.
3.1. Если класс найден, загрузка успешно завершена.
3.2. Если класс не найден, базовый Bootstrap Classloader попытается его загрузить.
4.1. Прошла успешно — загрузка класса завершена.
4.2. Не прошла успешно — управление передается к Extension Classloader.
5. Extension Classloader пытается загрузить класс, и если загрузка:
5.1. Прошла успешно — загрузка класса завершена.
5.2. Не прошла успешно — управление передается к System Classloader.
6. System Classloader пытается загрузить класс, и если загрузка:
6.1. Прошла успешно — загрузка класса завершена.
6.2. Не прошла успешно — генерируется исключение — ClassNotFoundException.
Тема загрузчиков классов обширна и ею не стоит пренебрегать. Чтобы ознакомиться с ней подробнее, советую прочесть эту статью, а мы не будем задерживаться и пойдем дальше.
12. Что такое Run-Time Data Areas?
PC Register — регистр ПК — локален для каждого потока и содержит адрес инструкции JVM, которую поток выполняет в данный момент.
JVM Stack — область памяти, которая используется как хранилище для локальных переменных и временных результатов. У каждого потока есть свой отдельный стек: как только поток завершается, этот стек также уничтожается. Стоит отметить, что преимуществом stack над heap является производительность, в то время как heap безусловно имеет преимущество в масштабе хранилища.
Native Method Stack — область данных для каждого потока, в которой хранятся элементы данных, аналогичные стеку JVM, для выполнения собственных (не Java) методов.
Heap — используется всеми потоками как хранилище которое содержит объекты, метаданные классов, массивы и т. д., которые создаются во время выполнения. Данная область создается при запуске JVM и уничтожается при завершении ее работы.
Method area — область метода — эта область времени выполнения общая для всех потоков и создается при запуске JVM. Он хранит структуры для каждого класса, такие как пул констант (Runtime Constant Pool — пул для хранения констант), код для конструкторов и методов, данные метода и т. д.
13. Что такое immutable object?
14. В чем особенность класса String?
Это самый популярный объект в Java, который применяют для разнообразных целей. По частоте использования он не уступает даже примитивным типам.
String — это immutable класс: при создании объекта данного класса его данные нельзя изменить (когда вы к некоторой строке добавляете + “другую строку”, как результат вы получите новую, третью строку). Неизменность класса String делает его потокобезопасным.
Класс String финализирован (имеет модификатор final ), поэтому его наследование невозможно.
У String есть свой пул строк, область памяти в heap, которая кеширует создаваемые строковые значения. В этой части серии, в 62 вопросе, я описывал строковой пул.