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

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

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

Статическая (static) же переменная привязана к статическому объекту класса и всегда существует в единственном экземпляре.

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

static Тип имя = значение;

Если статической переменной не присвоить стартовое значение, она инициализируется значением по умолчанию:

Тип Значение по умолчанию
byte
0
short
0
int
0
long
0
float
0.0
double
0.0
char
'\u0000'
(то же самое, что и
0
)
boolean
false
Object
и любые классы
null

Примеры:

Код Примечание
public static int WIDTH = 100;
public static String message = "Hello";
private static Scanner console;
private static int count = 0;
private static boolean flag;

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

ИмяКласса.переменная

Пример:

Переменная Класс Обращение к переменной вне класса
public static int WIDTH = 100;
Solution
Solution.WIDTH
public static String message = "Hello";
Main
Main.message
private static Scanner console;
JavaGame
Переменная private, вне класса не видна
private static int count = 0;
Counter
Переменная private, вне класса не видна
private static boolean flag;
Arithmetic
Переменная private, вне класса не видна


2. Отличие статических и нестатических переменных

Нестатические (обычные) переменные класса объявляются точно так же, как статические, только без ключевого слова static.

Чем же отличаются обычные и статические переменные?

Обычные переменные класса привязаны к объектам своего класса (экземплярам класса), статические переменные — к статическому объекту класса.

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

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

Пример:

Обращение к полю класса с использованием ссылки на объект класса
public class DataInfo
{
   public int value = 100;
}

public class Solution
{
   public static void main(String[] args)
   {
      DataInfo info = new DataInfo();
      System.out.println(info.value);
   }
}

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

Пример:

Обращение к статическому полю класса не используя ссылку на объект класса
public class DataInfo
{
   public static int value = 100;
}

public class Solution
{
   public static void main(String[] args)
   {
      System.out.println(DataInfo.value);
   }
}

Устройство в памяти:

Допустим, у нас есть класс Person с 4 полями: два статических, а два — нет.

public class Person
{
   public static int count = 0;
   public static int sum = 0;
   public int age = 0;
   public String name;
}

Сразу после загрузки класса

Когда Java-машина завершит загрузку класса Person, в памяти у нас будет наблюдаться такая картина:

Отличие статических и нестатических переменных

После создания первого объекта

Если мы создадим объект класса Person, картинка станет такой

Отличие статических и нестатических переменных 1

Обратите внимание, что хоть у объектов по две переменные, это разные переменные: у обычного объекта — обычные, у статического — статические.

Нужно больше объектов

Давайте создадим еще два объекта, типа Person. Новая картина будет выглядеть так:

Отличие статических и нестатических переменных 2

Обратите внимание: у каждого объекта есть собственная переменная age и name.



3 Удаление и добавление модификатора static

Из статической в обычную

Что будет, если мы возьмем статическую переменную и превратим ее в обычную: удалим у нее модификатор static? Например, у переменной static int sum.

Измененный код будет выглядеть так:

public class Person
{
   public static int count = 0;
   public int sum = 0;
   public int age = 0;
   public String name;
}

А в памяти мы получим такую картину:

Удаление и добавление модификатора static

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

Из обычной в статическую

Можно сделать и наоборот: добавить перед обычными переменными класса модификатор static, и тогда они исчезнут у всех объектов и появятся у статического объекта. Допустим, мы решили сделать переменные age и name статическими. Тогда код будет выглядеть так:

public class Person
{
   public static int count = 0;
   public int sum = 0;
   public static int age = 0;
   public static String name;
}

А в памяти мы получим уже такую картину:

Удаление и добавление модификатора static