Java static class что такое. Модификаторы в Java: static, final, abstract, synchronized, transient, volatile. Тип возвращаемого значения

Мы поговорим о модификаторах: какие бывают модификаторы, области видимости, модификаторы для классов, полей, методов. Думаю, будет не скучно.

Модификаторы в Java – это ключевые слова, которые придают классу, полю класса или методу определенные свойства.

Для обозначения видимости класса его методов и полей есть 4 модификатора доступа:

  • private члены класса доступны только внутри класса;
  • package-private или default (по умолчанию) члены класса видны внутри пакета;
  • protected члены класса доступны внутри пакета и в классах-наследниках;
  • public члены класса доступны всем.

Если Вы помните , то в конце, когда мы уже импортировали класс Cat, у нас все равно была ошибка компиляции.

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

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

Представьте, что у Вас есть класс который отображает объект некоего продукта. Например машина. У машины может быть цена. Вы создали поле цена и еще множество других полей, кучу методов которые отвечают за функционал. Все вроде хорошо. Ваш класс машина является частью огромного проекта и все довольны. Но допустим, что кто-то по ошибке или специально создал экземпляр класса автомобиль и поставил отрицательную цену. Разве может товар иметь отрицательную цену? Это очень примитивный пример и вряд ли такое может случиться в реальной жизни, но думаю, идея понятна. Иногда нужно дать доступ не напрямую, а через определенные методы. Может быть, что код отвечает за функционал другого кода, и Вы не хотите, чтобы кто-то изменял и редактировал часть Вашего. Для этого всего и есть ограничение доступа.

Модификатор доступа у конструкторов, методов и полей может быть любой. Класс может быть только либо public, либо default, причем в одном файле может находиться только один public класс.

Пока об модификаторах доступа будет достаточно. В статье «Объектно ориентированное программирование» мы о них поговорим подробнее, а сейчас давайте поговорим о других модификаторах которых, к стати, немало.

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

static модификатор перед методом или полем говорит о том, что они не принадлежат к экземпляру данного класса. Что это означает для нас? Когда мы описали поле класса или метод как static, его можно вызвать без использования экземпляра класса. То есть вместо такой конструкции: Cat cat = new Cat(); cat.method(), можно написать просто Cat.method(). При условии, что метод объявлен как static. Статические переменные едины для всех объектов класса. У них одна ссылка.

    public class Modificators {

    static int anotherStaticField = 5 ;

    public static void myStaticMethod() {

    someField = "My field" ;

    //nonStaticField = ""; ошибка компиляции

    //нельзя использовать нестатические поля

    //в статических методах

    public void myNonStaticMethod() {

    anotherStaticField = 4 ; //ститические поля можно использовать

    //в нестатических методах

    //main метод тоже имеет модификатор static

    new Modificators() .myNonStaticMethod () ;

    Modificators.myStaticMethod () ; //вызов статических методов и полей

    //через имяКласса.метод

Еще одно важное замечание, которое нужно сказать по поводу static модификаторов: статические поля инициализируются во время загрузки класса. Часто в разного рода тестах по Java можно встретить такой код:

Вопрос: что будет выведено на консоль? Нужно помнить, что static блок будет выведен первым при любом раскладе. Далее будет идти блок по умолчанию. Далее смотрите на скрин консоли:

Следующий модификатор, который мы рассмотрим будет final.

Думаю, слово final говорит само за себя. Применяя final модификатор Вы говорите, что поля не могут быть изменены, методы переопределены, а классы нельзя наследовать (о наследовании будет отдельная статья). Этот модификатор применяется только к классам, методам и переменным (также и к локальным переменным).

С модификатором final к методам и классам мы будем говорить в статье ООП.

Далее пойдут модификаторы, которые новичкам или читающим данный цикл статей с нуля будут не очень понятными. И хотя я пока не смогу Вам все объяснить (в силу того, что Вы не знаете сопутствующего материала), все же советую просто ознакомиться с ними. Когда придет время использования данных модификаторов, Вы уже будете понимать большинство терминов используемых ниже.

Модификатор synchronized — говорит о том, что метод может быть использован только одним потоком одновременно. Хотя, возможно, это Вам ни о чем не говорит, полезность этого модификатора будет видно, когда мы будем изучать многопоточность.

Модификатор transient — говорит о том, что во время сериализации объекта некоторое поле нужно игнорировать. Как правило, такие поля хранят промежуточные значения.

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

Модификатор native перед объявлением метода указывает что метод написан на другом языке программирования. Обычно на языке C.

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

Я еще не говорил о модификаторе abstract . О нем скажу вкратце, так как без знаний основ объектно ориентированного программирования говорить о нем не вижу смысла.

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

Подробнее о модификаторе abstract будем говорить в статье ООП.

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

Последнее обновление: 19.04.2018

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

Public static void main(String args) { }

Для объявления статических переменных, констант, методов и инициализаторов перед их объявлением указывается ключевое слово static .

Статические поля

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

Например, создадим статическую переменную:

Public class Program{ public static void main(String args) { Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 1 bob.displayId(); // Id = 2 System.out.println(Person.counter); // 3 // изменяем Person.counter Person.counter = 8; Person sam = new Person(); sam.displayId(); // Id = 8 } } class Person{ private int id; static int counter=1; Person(){ id = counter++; } public void displayId(){ System.out.printf("Id: %d \n", id); } }

Класс Person содержит статическую переменную counter, которая увеличивается в конструкторе и ее значение присваивается переменной id. То есть при создании каждого нового объекта Person эта переменная будет увеличиваться, поэтому у каждого нового объекта Person значение поля id будет на 1 больше чем у предыдущего.

Так как переменная counter статическая, то мы можем обратиться к ней в программе по имени класса:

System.out.println(Person.counter); // получаем значение Person.counter = 8; // изменяем значение

Консольный вывод программы:

Id = 1 Id = 2 3 Id = 8

Статические константы

Также статическими бывают константы, которые являются общими для всего класса.

Public class Program{ public static void main(String args) { double radius = 60; System.out.printf("Radisu: %f \n", radius); // 60 System.out.printf("Area: %f \n", Math.PI * radius); // 188,4 } } class Math{ public static final double PI = 3.14; }

Стоит отметить, что на протяжении всех предыдущих тем уже активно использовались статические константы. В частности, в выражении:

System.out.println("hello");

out как раз представляет статическую константу класса System. Поэтому обращение к ней идет без создания объекта класса System.

Статические инициализаторы

Статические инициализаторы предназначены для инициализации статических переменных, либо для выполнения таких действий, которые выполняются при создании самого первого объекта. Например, определим статический инициализатор:

Public class Program{ public static void main(String args) { Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 105 bob.displayId(); // Id = 106 } } class Person{ private int id; static int counter; static{ counter = 105; System.out.println("Static initializer"); } Person(){ id=counter++; System.out.println("Constructor"); } public void displayId(){ System.out.printf("Id: %d \n", id); } }

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

В самой программе создаются два объекта класса Person. Поэтому консольный вывод будет выглядеть следующим образом:

Static initializer Constructor Constructor Id: 105 Id: 106

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

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

Статические методы также относятся ко всему классу в целом. Например, в примере выше статическая переменная counter была доступна извне, и мы могли изменить ее значение вне класса Person. Сделаем ее недоступной для изменения извне, но доступной для чтения. Для этого используем статический метод:

Public class Program{ public static void main(String args) { Person.displayCounter(); // Counter: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Counter: 3 } } class Person{ private int id; private static int counter = 1; Person(){ id = counter++; } // статический метод public static void displayCounter(){ System.out.printf("Counter: %d \n", counter); } public void displayId(){ System.out.printf("Id: %d \n", id); } }

Теперь статическая переменная недоступна извне, она приватная. А ее значение выводится с помощью статического метода displayCounter. Для обращения к статическому методу используется имя класса: Person.displayCounter() .

При использовании статических методов надо учитывать ограничения: в статических методах мы можем вызывать только другие статические методы и использовать только статические переменные.

Вообще методы определяются как статические, когда методы не затрагиют состояние объекта, то есть его нестатические поля и константы, и для вызова метода нет смысла создавать экземпляр класса. Например:

Public class Program{ public static void main(String args) { System.out.println(Operation.sum(45, 23)); // 68 System.out.println(Operation.subtract(45, 23)); // 22 System.out.println(Operation.multiply(4, 23)); // 92 } } class Operation{ static int sum(int x, int y){ return x + y; } static int subtract(int x, int y){ return x - y; } static int multiply(int x, int y){ return x * y; } }

В данном случае для методов sum, subtract, multiply не имеет значения, какой именно экземпляр класса Operation используется. Эти методы работают только с параметрами, не затрагивая состояние класса. Поэтому их можно определить как статические.

Что такое static

В некоторых случаях желательно определить член класса, который будет использоваться независимо от любого объекта этого класса. Обычно обращение к члену класса должно выполняться только в сочетании с объектом его класса. Однако можно создать член класса, который может использоваться самостоятельно, без ссылки на конкретный экземпляр. Чтобы создать такой член, в начало его объявления нужно поместить ключевое слово static. Когда член класса объявлен как static (статический), он доступен до создания каких-либо объектов его класса и без ссылки на какой-либо объект. Статическими могут быть объявлены как методы, так и переменные. Наиболее распространенный пример статического члена - метод main (). Этот метод объявляют как static, поскольку он должен быть объявлен до создания любых объектов.

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

На методы, объявленные как static, накладывается ряд ограничений.

  • Они могут вызывать только другие статические методы.
  • Они должны осуществлять доступ только к статическим переменным.
  • Они ни коим образом не могут ссылаться на члены типа this или super. (Ключевое слово super связано с наследованием и описывается в следующей главе.)

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

// Демонстрация статических переменных, методов и блоков.
class UseStatic {
static int a = 3;
static int b;
static void meth(int x) {
System.out.println ("x = " + x) ;
System.out.println ("a = " + a);
System.out.println("b = " + b) ;
}
static {
System.out.println("Статический блок инициализирован.");
b = a * 4;
}

meth(42);
}
}

Сразу после загрузки класса UseStatic программа выполняет все операторы static. Вначале значение а устанавливается равным 3, затем программа выполняет блок static, который выводит сообщение, а затем инициализирует переменную b значением а*4, или 12. Затем программа вызывает метод main (), который обращается к методу meth (), передавая параметру х значение 42. Три оператора println () ссылаются на две статических переменные а и b на локальную переменную х.

Вывод этой программы имеет такой вид:

Статический блок инициализирован, х = 42 а = 3 b = 12

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

имя_класса.метод()

Здесь имя_класса - имя класса, в котором объявлен метод тип static. Как видите, этот формат аналогичен применяемому для вызова нестатических методов через переменные объектных ссылок. Статическая переменная доступна аналогичным образом - посредством операции точки, следующей за именем класса. Так в Java реализованы управляемые версии глобальных методов и переменных.

Приведем пример. Внутри метода main () обращение к статическому методу callme () и статической переменной b осуществляется посредством имени их класса StaticDemo.

class StaticDemo {
static int a = 42;
static int b = 99;
static void callme () {
System.out.println("a = " + a);
}
}
class StaticByName {
public static void main(String args) {
StaticDemo.callme () ;
System.out.println("b = " + StaticDemo.b);
}
}

Вывод этой программы выглядит следующим образом.

9 ответов

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

  • Объявить свой класс final - Предотвращает расширение класса, поскольку расширение статического класса не имеет смысла
  • Сделать конструктор private - предотвращает создание экземпляра по клиентскому коду, поскольку нет смысла создавать статический класс
  • Создайте все элементы и функции класса static . Поскольку класс не может быть инстанцирован, методы экземпляров не могут быть вызваны или доступны поля экземпляра
  • Обратите внимание, что компилятор не помешает вам объявить экземпляр (нестатический). Проблема будет появляться только в том случае, если вы попытаетесь вызвать член экземпляра

Простой пример из приведенных выше предложений:

Public class TestMyStaticClass { public static void main(String args){ MyStaticClass.setMyStaticMember(5); System.out.println("Static value: " + MyStaticClass.getMyStaticMember()); System.out.println("Value squared: " + MyStaticClass.squareMyStaticMember()); // MyStaticClass x = new MyStaticClass(); // results in compile time error } } // A top-level Java class mimicking static class behavior public final class MyStaticClass { private MyStaticClass () { // private constructor myStaticMember = 1; } private static int myStaticMember; public static void setMyStaticMember(int val) { myStaticMember = val; } public static int getMyStaticMember() { return myStaticMember; } public static int squareMyStaticMember() { return myStaticMember * myStaticMember; } }

Что хорошего в статических классах? Хорошее использование статического класса заключается в определении одноразовых, служебных и/или библиотечных классов, где инстанцирование не имеет смысла. Отличным примером является класс Math, который содержит некоторые математические константы, такие как PI и E, и просто обеспечивает математические вычисления. Требование создания экземпляра в таком случае было бы ненужным и запутанным. См. класс Java Math . Обратите внимание, что он является окончательным, и все его члены статичны. Если Java разрешал классы верхнего уровня объявляться статическими, то класс Math действительно был бы статическим.

Ну, у Java есть "статические вложенные классы", но они совсем не то же самое, что и статические классы С#, если это то, откуда вы пришли. Статический вложенный класс - это просто тот, который не подразумевает ссылку на экземпляр внешнего класса.

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

В Java нет такой вещи, как статический класс верхнего уровня.

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

Пример:

Public class A { public static class B { } }

Поскольку class B объявлен static, вы можете явно создать экземпляр как:

B b = new B();

Обратите внимание, что если class B не был объявлен static, чтобы сделать его автономным, вызов объекта экземпляра выглядел бы следующим образом:

A a= new A(); B b = a.new B();

Что происходит, когда члены внутри class объявлены как static ..? Доступ к этим элементам возможен без создания экземпляра class . Поэтому создание внешнего класса (класс верхнего уровня) static не имеет смысла. Поэтому это не допускается.

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

Public class A { public static class B { } }

Теперь, в другом классе C , можно получить доступ к классу B без создания экземпляра класса A .

Public class C { A.B ab = new A.B(); }

static классы могут иметь членов non-static . Только класс становится статичным.

Но если ключевое слово static удалено из класса B , к нему нельзя получить доступ напрямую, не создавая экземпляр A .

Public class C { A a = new A(); A.B ab = a. new B(); }

Но мы не можем иметь static членов внутри внутреннего класса non-static .

Увидев, что это лучший результат в Google для "статического класса java", и лучший ответ здесь нет, я решил, что добавлю его. Я интерпретирую вопрос OP как относительно статических классов в С#, которые известны как одиночные точки в мире Java. Для тех, кто не знает, в С# ключевое слово "статическое" может быть применено к объявлению класса, что означает, что результирующий класс никогда не может быть создан.

Отрывок из "Эффективного Java - второго издания" Джошуа Блоха (широко известный как один из лучших руководств по стилю Java):

Начиная с версии 1.5, существует третий подход к реализации синглетонов. Просто введите тип перечисления с одним элементом:

// Enum singleton - the preferred approach public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }

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

Модификатор static в Java напрямую связан с классом, если поле статично, значит оно принадлежит классу, если метод статичный, аналогично - он принадлежит классу. Исходя из этого, можно обращаться к статическому методу или полю используя имя класса. Например, если поле count статично в классе Counter , значит, вы можете обратиться к переменной запросом вида: Counter.count . Конечно, следует учитывать модификаторы доступа. Например, поля private доступны только внутри класса, в котором они объявлены. Поля protected доступны всем классам внутри пакета (package ), а также всем классам-наследникам вне пакета. Для более подробной информации ознакомьтесь со статьей “private vs protected vs public ”. Предположим, существует статический метод increment() в классе Counter , задачей которого является инкрементирование счётчика count . Для вызова данного метода можно использовать обращение вида Counter.increment() . Нет необходимости создавать экземпляр класса Counter для доступа к статическому полю или методу. Это фундаментальное отличие между статическими и НЕ статическими объектами (членами класса). Важное замечание. Не забывайте, что статические члены класса напрямую принадлежат классу, а не его экземпляру. То есть, значение статической переменной count будет одинаковое для всех объектов типа Counter . В этой статье мы рассмотрим основополагающие аспекты применения модификатора static в Java, а также некоторые особенности, которые помогут понять ключевые концепции программирования.

Что должен знать каждый программист о модификаторе Static в Java.

В этом разделе мы рассмотрим основные моменты использования статических методов, полей и классов. Начнём с переменных.

    Вы НЕ можете получить доступ к НЕ статическим членам класса, внутри статического контекста, как вариант, метода или блока. Результатом компиляции приведенного ниже кода будет ошибка:

    public class Counter { private int count; public static void main (String args ) { System. out. println (count) ; //compile time error } }

    Это одна из наиболее распространённых ошибок допускаемых программистами Java, особенно новичками. Так как метод main статичный, а переменная count нет, в этом случае метод println , внутри метода main выбросит “Compile time error”.

    В отличие от локальных переменных, статические поля и методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите - «залочивании» классом. Поэтому при использовании статических переменных, убедитесь, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких как «состояние гонки» (race condition).

    Статические методы имеют преимущество в применении, т.к. отсутствует необходимость каждый раз создавать новый объект для доступа к таким методам. Статический метод можно вызвать, используя тип класса, в котором эти методы описаны. Именно поэтому, подобные методы как нельзя лучше подходят в качестве методов-фабрик (factory), и методов-утилит (utility). Класс java.lang.Math - замечательный пример, в котором почти все методы статичны, по этой же причине классы-утилиты в Java финализированы (final).

    Другим важным моментом является то, что вы НЕ можете переопределять (Override) статические методы. Если вы объявите такой же метод в классе-наследнике (subclass), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса (superclass) вместо переопределения. Это явление известно как сокрытие методов (hiding methods). Это означает, что при обращении к статическому методу, который объявлен как в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:

    class Vehicle { public static void kmToMiles (int km) { System. out. println ("Внутри родительского класса/статического метода" ) ; } } class Car extends Vehicle { public static void kmToMiles (int km) { System. out. println ("Внутри дочернего класса/статического метода " ) ; } } public class Demo { public static void main (String args ) { Vehicle v = new Car () ; v. kmToMiles (10 ) ; } }

    Вывод в консоль:

    Внутри родительского класса/статического метода

    Код наглядно демонстрирует: несмотря на то, что объект имеет тип Car , вызван статический метод из класса Vehicle , т.к. произошло обращение к методу во время компиляции. И заметьте, ошибки во время компиляции не возникло!

    Объявить статическим также можно и класс, за исключением классов верхнего уровня. Такие классы известны как «вложенные статические классы» (nested static class). Они бывают полезными для представления улучшенных связей. Яркий пример вложенного статического класса - HashMap.Entry , который предоставляет структуру данных внутри HashMap . Стоит заметить, также как и любой другой внутренний класс, вложенные классы находятся в отдельном файле.class. Таким образом, если вы объявили пять вложенных классов в вашем главном классе, у вас будет 6 файлов с расширением.class. Ещё одним примером использования является объявление собственного компаратора (Comparator), например компаратор по возрасту (AgeComparator) в классе сотрудники (Employee).

    Модификатор static также может быть объявлен в статичном блоке, более известным как «Статический блок инициализации» (Static initializer block), который будет выполнен во время загрузки класса. Если вы не объявите такой блок, то Java соберёт все статические поля в один список и выполнит его во время загрузки класса. Однако, статичный блок НЕ может пробросить перехваченные исключения, но может выбросить не перехваченные. В таком случае возникнет «Exception Initializer Error». На практике, любое исключение возникшее во время выполнения и инициализации статических полей, будет завёрнуто Java в эту ошибку. Это также самая частая причина ошибки «No Class Def Found Error», т.к. класс не находился в памяти во время обращения к нему.

    Полезно знать, что статические методы связываются во время компиляции, в отличие от связывания виртуальных или не статических методов, которые связываются во время исполнения на реальном объекте. Следовательно, статические методы не могут быть переопределены в Java, т.к. полиморфизм во время выполнения не распространяется на них. Это важное ограничение, которое необходимо учитывать, объявляя метод статическим. В этом есть смысл, только тогда, когда нет возможности или необходимости переопределения такого метода классами-наследниками. Методы-фабрики и методы-утилиты хорошие образцы применения модификатора static . Джошуа Блох выделил несколько преимуществ использования статичного метода-фабрики перед конструктором, в книге «Effective Java », которая является обязательной для прочтения каждым программистом данного языка.

    Важным свойством статического блока является инициализация. Статические поля или переменные инициализируются после загрузки класса в память. Порядок инициализации сверху вниз, в том же порядке, в каком они описаны в исходном файле Java класса. Поскольку статические поля инициализируются на потокобезопасный манер, это свойство также используется для реализации паттерна Singleton . Если вы не используется список Enum как Singleton , по тем или иным причинам, то для вас есть хорошая альтернатива. Но в таком случае необходимо учесть, что это не «ленивая» инициализация. Это означает, что статическое поле будет проинициализировано ещё ДО того как кто-нибудь об этом «попросит». Если объект ресурсоёмкий или редко используется, то инициализация его в статическом блоке сыграет не в вашу пользу.

    Во время сериализации, также как и transient переменные, статические поля не сериализуются. Действительно, если сохранить любые данные в статическом поле, то после десериализации новый объект будет содержать его первичное (по-умолчанию) значение, например, если статическим полем была переменная типа int , то её значение после десериализации будет равно нулю, если типа float – 0.0, если типа Object – null . Честно говоря, это один из наиболее часто задаваемых вопросов касательно сериализации на собеседованиях по Java. Не храните наиболее важные данные об объекте в статическом поле!

    И напоследок, поговорим о static import . Данный модификатор имеет много общего со стандартным оператором import , но в отличие от него позволяет импортировать один или все статические члены класса. При импортировании статических методов, к ним можно обращаться как будто они определены в этом же классе, аналогично при импортировании полей, мы можем получить доступ без указания имени класса. Данная возможность появилась в Java версии 1.5, и при должном использовании улучшает читабельность кода. Наиболее часто данная конструкция встречается в тестах JUnit , т.к. почти все разработчики тестов используют static import для assert методов, например assertEquals() и для их перегруженных дубликатов. Если ничего не понятно – добро пожаловать за дополнительной информацией .

    На этом всё. Все вышеперечисленные пункты о модификаторе static в Java обязан знать каждый программист. В данной статье была рассмотрена базовая информация о статических переменных, полях, методах, блоках инициализации и импорте. В том числе некоторые важные свойства, знание которых является критичным при написании и понимании программ на Java. Я надеюсь, что каждый разработчик доведёт свои навыки использования статических концептов до совершенства, т.к. это очень важно для серьёзного программирования."