Перейти к содержимому

Public static final java что это

  • автор:

Ключевые слова static и final

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

public static void main(String[] args) { . }

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

class Point { static int cnt; int x, y; }

Спрашивается: в чем отличие между полями x, y и статическим полем cnt? Лучше всего это продемонстрировать на следующем рисунке.

Когда создаются объекты класса Point:

Point pt1 = new Point(); Point pt2 = new Point();

то в каждый из них будут помещены копии полей x, y, но поле cnt скопировано не будет, оно останется на уровне класса Point и станет общим для всех экземпляров этого класса. То есть, при обращении к статической переменной cnt из любого экземпляра класса, например, вот так:

class Point { static int cnt; int x, y; { x = y = -1; } Point() { cnt++; } }

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

System.out.println(Point.cnt);

Обратите внимание, мы обращаемся к статическому полю cnt напрямую через класс Point, т.к. оно хранится непосредственно в нем. То же самое будет, если обратиться к этой переменной через ссылку pt1:

System.out.println(pt1.cnt);

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

{ cnt = 0; x = y = -1; }

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

static int cnt = 0;

Второй способ подразумевает использование статического инициализатора:

static { cnt = 0; }

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

Вот так ведут себя статические переменные. Чтобы лучше понять логику их функционирования, отмечу, что ключевое слово static указывает компилятору создавать переменную один раз в процессе работы программы в определенной области памяти и не перемещать ее куда бы то ни было (в другую область памяти), в том числе не создавать ее копии. Поэтому, статическая переменная объявленная в классе Point создается внутри него и не переходит в экземпляры этого класса, а остается общей для всех.

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

Похожим образом ведут себя и статические методы классов: они принадлежат непосредственно классу и не дублируются в его экземпляры. Давайте для примера добавим статический метод в класс Point:

class Point { private static int cnt = 0; int x, y; . public static int getCounter() { return cnt; } }

Мы здесь сделали поле cnt приватным, а доступ к нему – через геттер getCounter. И обратите внимание в какой последовательности записываются модификаторы доступа, слово static и тип поля или метода:

Соответственно, в функции main мы теперь должны прописать этот геттер вместо прямого обращения к cnt:

System.out.println(Point.getCounter());

В итоге картина расположения статических и нестатических полей будет следующей:

Здесь статический метод getCounter() общий для всех экземпляров класса Point. Фактически, он принадлежит только классу Point, но также может вызываться из его объектов. Именно поэтому, мы можем обращаться к нему непосредственно через класс Point, используя конструкцию:

Так можно делать с любыми статическими методами и полями класса. Но статичность налагает и определенные ограничения. В частности, метод getCounter() может получать доступ к статической переменной cnt, но не может работать с динамическими полями x, y. Действительно, если написать что-то вроде:

public static int getCounter() { return x; }

то возникнет ошибка, так как статический метод на уровне класса просто «не видит» переменные x, y в экземплярах. Все что ему доступно – это другие статические методы и поля класса Point. То есть, из статических методов можно вызывать только другие статические методы и обращаться исключительно к статическим переменным. Или же, создавать объекты и переменные непосредственно внутри статического метода:

public static int getCounter() { int x = 5; return x; }

Отчасти это мы делаем в статическом методе main().

Статический импорт

Наконец, есть еще такое понятие как статический импорт. Что это такое? Все достаточно просто. Если в пакете имеются классы со статическими элементами, например, в пакете System мы обращаемся к классу out со статическим методом println(), то простой импорт:

import java.lang.System.*;

не импортирует такой класс, только классы без статических данных. А вот если добавить ключевое слово static:

то получим статический импорт и класс out появится в нашем текущем модуле.

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

Ключевое слово final

В заключении этого занятия я расскажу об еще одном ключевом слове final. Оно позволяет задавать константы в языке Java. Например, если у поля cnt добавить это ключевое слово, то дальнейшее изменение переменной cnt станет невозможным:

private static final int cnt = 0;

Опять же, обратите внимание на очередность ключевых слов. Конечно, это странный пример, поэтому давайте оставим переменную cnt как обычную статическую, а в класс Point добавим еще одно поле с указанием final:

final int MAX_COORD = 10;

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

final int MAX_COORD;

Ключевое слово final можно использовать и у методов. Но особенность их поведения будет проявляться только в момент наследования. Поэтому я буду говорить об этом в теме наследования классов.

Путь кодера

Подвиг 1. Объявите класс ShopItem для представления продуктов в магазине с полями: id (идентификатор – целое число), название товара, габариты, вес, цена. Поле id должно быть уникальным для каждого объекта класса. Это следует реализовать через статическую переменную, которая подсчитывает количество создаваемых экземпляров.

Подвиг 2. Реализовать класс Rect для описания прямоугольника с полями: x1, y1, x2, y2 – координат вершин верхнего правого и нижнего левого углов. Прописать два статических метода для вычисления ширины и высоты прямоугольника. В качестве параметра этим методам передавать ссылку на экземпляр класса Rect, для которого выполняется вычисление.

Подвиг 3. Реализовать класс Singleton, в котором определить статический метод getInstance(). Этот метод должен возвращать экземпляр класса, если он еще не создавался. Иначе, возвращается ссылка на ранее созданный экземпляр. Также следует запретить создание объектов класса Singleton напрямую через оператор new. (Полученная реализация будет гарантировать существование только одного экземпляра класса в процессе работы программы и, фактически, является примером известного паттерна singleton).

Видео по теме

#11 Концепция объектно-ориентированного программирования (ООП)

#12 Классы и создание объектов классов

#13 Конструкторы, ключевое слово this, инициализаторы

#14 Методы класса, сеттеры и геттеры, public, private, protected

#15 Пакеты, модификаторы конструкторов и классов

#16 Ключевые слова static и final

#17 Внутренние и вложенные классы

#18 Как делается наследование классов

#19 Ключевое слово super, оператор instanceof

#20 Модификаторы private и protected, переопределение методов, полиморфизм

#21 Абстрактные классы и методы

#22 Интерфейсы — объявление и применение

#23 Интерфейсы — приватные, статические и дефолтные методы, наследование интерфейсов

#24 Анонимные внутренние классы

#25 Перечисления (enum)

#26 Обобщения классов (Generics)

#27 Ограничения типов, метасимвольные аргументы, обобщенные методы и конструкторы

#28 Обобщенные интерфейсы, наследование обобщенных классов

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

Ключевое слово «final» в Java: как это работает?

Типичная проблема, с которой сталкиваются новички в Java — понимание работы ключевого слова final . В Java это ключевое слово используется для того, чтобы указать, что значение переменной не должно меняться. Но есть нюансы, которые могут запутать новичка. Рассмотрим пример.

import java.util.ArrayList; import java.util.List; class Test < private final List foo; public Test() < foo = new ArrayList(); foo.add("foo"); >public static void main(String[] args) < Test t = new Test(); t.foo.add("bar"); System.out.println("print - " + t.foo); >>

В этом коде используется ключевое слово final для переменной foo . И, несмотря на это, в конструкторе класса и в main методе к этому списку добавляются элементы. Код работает и не вызывает ошибок компиляции.

Теперь давайте попробуем изменить переменную на static :

private static final List foo;

И в этом случае мы увидим ошибку компиляции. Почему так происходит? Как на самом деле работает final ?

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

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

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

final (Java) — final (Java)

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

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

  • 1 Конечные классы
  • 2 Конечные методы
  • 3 Конечные переменные
    • 3.1 Конечные переменные во вложенных объектах
    • 3.2 Конечные и внутренние классы
    • 3.3 Пустой final

    Конечные классы

    A final class не могут быть разделены на подклассы. Поскольку это может обеспечить повышение безопасности и эффективности, многие классы стандартной библиотеки Java являются окончательными, например java.lang.System и java.lang. String .

    общедоступный конечный класс MyFinalClass открытый класс ThisIsWrong extends MyFinalClass // запрещено

    Заключительные методы

    Последний метод нельзя переопределить или скрыть подклассами. Это используется для предотвращения неожиданного поведения подкласса, изменяющего метод, который может иметь решающее значение для функции или согласованности класса.

    public class Base public final void m2 () public static void m3 () public static final void m4 () > открытый класс Derived extends Base // ОК, переопределение Base # m1 () public void m2 () // Запрещено public static void m3 () // ОК, скрытие Base # m3 () public static void m4 () // запрещено>

    Распространенным заблуждением является то, что объявление метода как final повышает эффективность, позволяя компилятору напрямую вставлять метод везде, где он вызывается (см. встроенное расширение ). Поскольку метод загружается во время выполнения , компиляторы не могут этого сделать. Только среда выполнения и компилятор JIT точно знают, какие классы были загружены, и поэтому только они могут принимать решения о том, когда встраивать, является ли метод окончательным.

    Машина Компиляторы кода, которые генерируют непосредственно исполняемый, зависящий от платформы машинный код, являются исключением. При использовании статической компоновки компилятор может с уверенностью предположить, что методы и переменные, вычисляемые во время компиляции, могут быть встроены.

    Конечные переменные

    A final variable могут быть инициализированы только один раз, либо через инициализатор, либо через оператор присваивания. Ее не нужно инициализировать в момент объявления: это называется «пустой конечной» переменной. Пустая конечная переменная экземпляра класса должна быть определенно назначена в каждом конструкторе класса, в котором она объявлена; аналогично, пустая конечная статическая переменная должна быть определенно назначена в статическом инициализаторе класса, в котором она объявлена; в противном случае в обоих случаях возникает ошибка времени компиляции. (Примечание: если переменная является ссылкой, это означает, что переменная не может быть повторно привязана для ссылки на другой объект. Но объект, на который она ссылается, все еще является изменяемым, если он был изначально изменяемым.)

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

    public class Sphere

    Любая попытка переназначить radius , xPos , yPos или zPos приведет к ошибка компиляции. Фактически, даже если конструктор не устанавливает конечную переменную, попытка установить ее вне конструктора приведет к ошибке компиляции.

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

    public final Position pos;

    , где pos — это объект с тремя свойствами: pos.x , pos.y и pos.z . Тогда pos нельзя присвоить, но можно назначить три свойства, если они сами не являются окончательными.

    Как и полная неизменяемость, использование конечных переменных имеет большие преимущества, особенно при оптимизации. Например, Sphere , вероятно, будет иметь функцию, возвращающую его объем; знание того, что его радиус постоянен, позволяет нам запоминать вычисленный объем. Если у нас относительно мало Sphere и их тома нам нужны очень часто, прирост производительности может быть значительным. Создание радиуса Sphere final сообщает разработчикам и компиляторам, что такого рода оптимизация возможна во всем коде, который использует Sphere .

    Хотя это, похоже, нарушает принцип final , следующее является допустимым заявлением:

    for (final SomeObject obj: someList) 

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

    Конечные переменные во вложенных объектах

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

    Если приведенная выше конструкция нарушается из-за наличия в дереве объекта, который не является неизменяемым, ожидание не выполняется, что все, что доступно через конечную переменную, является постоянным. Например, следующий код определяет систему координат, начало которой всегда должно быть в (0, 0). Однако источник реализуется с использованием java.awt.Point , и этот класс определяет свои поля как общедоступные и изменяемые. Это означает, что даже при достижении объекта origin по пути доступа только с конечными переменными, этот объект все равно можно изменить, как показано в приведенном ниже примере кода.

    импортировать java.awt.Point; открытый класс FinalDemo > public static void main (String args) >

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

    Чтобы предотвратить эту нежелательную ситуацию, общее требование состоит в том, что все поля неизменяемого объекта должны быть окончательными, а типы этих полей сами должны быть неизменяемыми. Это запрещает использование java.util.Date и java.awt.Point и некоторых других классов в таких неизменяемых объектах.

    Final и внутренние классы

    Когда анонимный внутренний класс определен в теле метода, все переменные объявлены final в области видимости этот метод доступен из внутреннего класса. Для скалярных значений после назначения значение переменной final не может измениться. Для значений объекта ссылка не может измениться. Это позволяет компилятору Java «захватывать» значение переменной во время выполнения и сохранять копию как поле во внутреннем классе. После завершения работы внешнего метода и удаления его кадра стека исходная переменная исчезает, но частная копия внутреннего класса сохраняется в собственной памяти класса.

    импортировать javax.swing. *; public class FooGUI  >); >>

    Пустой финал

    Пустой финал, который был введен в Java 1.1, является конечной переменной, в объявлении которой отсутствует инициализатор. До версии Java 1.1 последняя переменная должна была иметь инициализатор. Бланк финала, по определению «финала», может быть назначен только один раз. т.е. он должен быть не назначен, когда происходит присвоение. Для этого компилятор Java выполняет анализ потока, чтобы гарантировать, что для каждого присвоения пустой конечной переменной переменная определенно не назначена перед назначением; в противном случае возникает ошибка времени компиляции.

    final boolean hasTwoDigits; if (number>= 10 number < 100) < hasTwoDigits = true; >if (number>-100 number 

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

    final boolean isEven; if (number% 2 == 0) System.out.println (isEven); // ошибка компиляции, потому что переменная не была назначена в другом случае.

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

    boolean isEven; // * not * final if (number% 2 == 0) System.out.println (isEven); // Такая же ошибка компиляции, потому что не- final переменная не была назначена в else-case.

    C / C ++ аналог конечных переменных

    В C и C ++ аналогичной конструкцией является const ключевое слово. Это существенно отличается от final в Java, в основном тем, что является квалификатором типа : const is часть типа, а не только часть идентификатора (переменной). Это также означает, что постоянство значения может быть изменено кастом ng (явное преобразование типа), в данном случае известное как «константное приведение». Тем не менее, отказ от константности и последующее изменение объекта приводит к неопределенному поведению, если объект был первоначально объявлен const . final Java — это строгое правило, из-за которого невозможно скомпилировать код, который напрямую нарушает или обходит последние ограничения. Однако с помощью отражения часто все еще можно изменить конечные переменные. Эта функция в основном используется при десериализации объектов с конечными членами.

    Кроме того, поскольку C и C ++ предоставляют указатели и ссылки напрямую, существует различие между постоянством самого указателя и постоянством данных, на которые указывает указатель. Применение const к самому указателю, как в SomeClass * const ptr , означает, что ссылочное содержимое может быть изменено, но сама ссылка не может (без преобразования). Это использование приводит к поведению, которое имитирует поведение ссылки на переменную final в Java. Напротив, при применении const только к указанным данным, как в const SomeClass * ptr , содержимое не может быть изменено (без приведения), но сама ссылка может. И ссылка, и содержимое, на которое ссылаются, могут быть объявлены как const .

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

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

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

    • java.util.Objects содержит статические служебные операции для метода объекта.
    • java.util.Collections состоит исключительно из статических методов, которые работают с коллекциями или возвращают их.

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

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

    • статические методы;
    • статические переменные;
    • статические вложенные классы;
    • статические блоки.

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

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

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

    public class StaticExample public static void add(int a, int b) System.out.println(a+b); 
    >

    public void multiply(int a, int b) System.out.println(a*b);
    >
    public static void main(String[] args) /** Вызов статического метода **/
    StaticExample.add(1, 2);

    /** Вызов не-статического метода**/
    StaticExample staticExample = new StaticExample();
    staticExample.multiply(1, 2);
    >
    >

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

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

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

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

    public class VariableExample public String normalVariable = null; 
    public static String staticVariable = null;
    public static void main(String[] args) VariableExample firstExample = new VariableExample();
    firstExample.normalVariable = "Hello";
    firstExample.staticVariable = "Hello";//Это то же самое, что VariableExample.staticVariable = "Hello"
    VariableExample secondExample = new VariableExample();
    System.out.println("normalVariable: "+ secondExample.normalVariable);
    System.out.println("staticVariable: "+ secondExample.staticVariable);
    >
    >

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

    firstExample.staticVariable = “Hello”

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

    VariableExample.staticVariable = “Hello”

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

    normalVariable: nullstaticVariable: Hello

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

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

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

    static >

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

    public class VariableExample public static String staticVariable = null; 

    static staticVariable = "Hello Variable";
    >

    public static void main(String[] args) System.out.println(staticVariable);
    >
    >

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

    public class VariableExample public static String staticVariable = null; 

    static staticVariable = "Hello Variable";
    >

    static staticVariable = "Hello Again";
    >

    public static void main(String[] args) System.out.println(staticVariable);
    >
    >

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

    Hello Again

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

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

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

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

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

    public class InnerClassExample public String outerElement; 
    private String outerPrivateElement;
    private void outerMethod()
    >
    public static class MyStaticInnerClass public void myFunction() System.out.println("calling static class inner function");
    >
    >
    public class MyInnerClass public void myAnotherFunction() outerElement = "sample";
    outerPrivateElement ="Hello Private";
    outerMethod();
    >
    >
    public static void main(String[] args) /**Вызов статического внутренего класса **/
    InnerClassExample.MyStaticInnerClass staticInner = new InnerClassExample.MyStaticInnerClass();
    staticInner.myFunction();
    /*Вызов внутреннего класса **/
    InnerClassExample.MyInnerClass innerClass = new InnerClassExample().new MyInnerClass();
    innerClass.myAnotherFunction();
    >
    >

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

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

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

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

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

    • Конечная переменная предназначена для создания постоянных значений.
    • Конечный метод предотвращает переопределение метода.
    • Конечный класс предотвращает наследование.

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

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

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

    • Инициализировать конечную переменную, когда она будет объявлена. Это самый распространенный подход. Если конечная переменная не инициализирована при объявлении, она называется пустой конечной переменной. Ниже приведены два способа инициализации пустой конечной переменной.
    • Пустая конечная переменная может быть инициализирована внутри блока инициализатора экземпляра или внутри конструктора. Если в классе несколько конструкторов, то переменную необходимо инициализировать во всех из них, в противном случае во время компиляции появится ошибка.
    • Пустая конечная статическая переменная может быть инициализирована в статическом блоке.
    public class FinalVariableExample public final String MY_VARIABLE_1 = "Variable Initialized"; 
    public final static String MY_VARIABLE_2;
    public final String MY_VARIABLE_3;
    public final String MY_VARIABLE_4 ;

    static MY_VARIABLE_2 = "Static Varible Initialized";
    >

    MY_VARIABLE_3 = "block Initialized";
    >

    public FinalVariableExample() MY_VARIABLE_4 = "Constructor Initialized";
    >

    >

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

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

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

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

    Первое, безусловно, заключается в предотвращении наследования, так как конечные классы не могут быть расширены. Например, все классы-оболочки, такие как Integer , Float и т. д. — конечные классы.

    public final class MyFinalClass 
    >

    public class MyClass extends MyFinalClass
    >

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

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

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

    Когда метод объявляется с ключевым словом final , он называется конечным методом. Такой метод не может быть переопределен. Это присутствует в классе Object — ряд его методов конечные. С ключевым словом final объявляются методы, для которых необходимо следовать одной и той же реализации во всех производных классах. Фрагмент ниже иллюстрирует метод с ключевым словом final :

    public class MyParentClass public final void myFinalMethod() . 
    >
    >

    public class MyClass extends MyParentClass public final void myFinalMethod() .
    >
    >

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

    Надеемся, теперь вы хорошо поняли ключевые слова static и final .

    • Используй Async/Await в JavaScript, как профессионал
    • Введение в байт-код Java
    • Жизненный цикл потока в Java

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

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