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

Кроме статических переменных, в классах могут быть и статические методы.

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

Чтобы вызвать обычный метод у класса, сначала нужно создать объект этого класса, а только потом вызвать метод у объекта. Вызвать обычный метод не у объекта, а у класса нельзя.

Пример:

Вызвать нестатический метод у класса нельзя!
public class DataInfo
{
   public int getValue()
   {
      return 100;
   }
}

public class Solution
{
   public static void main(String[] args)
   {
      System.out.println(DataInfo.getValue()); // тут будет ошибка!
   }
}

А чтобы вызвать статический метод, достаточно чтобы просто существовал статический объект класса (который всегда существует после загрузки класса в память). Именно поэтому метод main() — статический. Он привязан к статическому объекту класса, для его вызова не нужно создавать никакие объекты.

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

static тип имя(параметры)
{
   код метода
}

Примеры:

Код Примечание
public class Solution
{
   public static void main(String args[])
   {
      test();
   }

   public static void test()
   {
      int d = 2/0;
   }
}


Метод main вызывается Java-машиной командой вида: Solution.main();



Статический метод test() вызывается в статическом методе main().

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

Тип имя = ИмяКласса.имяМетода(параметры)

Примеры:

Код Статический метод
int x = Math.min(a, b);
int min(int a, int b)
Thread.sleep(200);
void sleep(long ms)
Path path = Path.of("c:\\readme.txt");
Path of(String str)

undefined
13
Задача
Java Syntax Pro, 13 уровень, 1 лекция
Недоступна
Автоупаковка
В классе Solution представлены 8 переменных примитивных типов с именами вида типValue. Для каждой из этих переменных необходимо создать объекты-обертки и присвоить им имена вида типValueBox. Для создания объектов-оберток используй метод Тип.valueOf(примитив). Пример переменной объекта-обертки: Integ

2. Статические vs Обычные методы

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

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

Отличия двух типов методов можно выразить в таблице:

Способность Обычный метод Статический метод
Есть связь с экземпляром класса Да Нет
Может вызывать обычные методы класса Да Нет
Может вызывать статические методы класса Да Да
Может обращаться к обычным переменным класса Да Нет
Может обращаться к статическим переменным класса Да Да
Может быть вызван у объекта Да Да
Может быть вызван у класса Нет Да

Зачем такие методы нужны, если они так сильно ограничены? Все дело в том, что у такого подхода тоже есть свои преимущества.

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

Во-вторых, иногда бывает нужно, чтобы переменная была в единственном экземпляре. Как, например, переменная System.out (статическая переменная out класса System).

И, в-третьих, иногда нужно вызвать метод еще до того, как будет возможность создавать какие-то объекты. Например, вызов метода main(), с которого начинается выполнение программы: его вызывает Java-машина до создания экземпляра класса.

Есть связь с экземпляром класса

При вызове обычного метода в него передается скрытый параметр — объект, у которого его вызывали. Этот параметр имеет имя this. Именно этот скрытый параметр — ссылка на объект, у которого вызвали метод — и отличает обычные методы от статических.

У статических методов такого скрытого параметра нет, поэтому внутри статических методов нельзя пользоваться ключевым словом this, и из статического метода нельзя вызвать нестатический: ссылку на экземпляр класса попросту неоткуда взять.

Может вызывать обычные методы класса

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

Код Как оно работает
int min(int a, int b)
{
   return a < b ? a : b;
}

int min(int a, int b, int c)
{
   int t = min(a, b);
   return min(t, c);
}
int min(int a, int b)
{
   return a < b ? a : b;
}

int min(int a, int b, int c)
{
   int t = this.min(a, b);
   return this.min(t, c);
}

Именно поэтому нельзя вызвать обычный метод из статического. Внутри статического метода просто нет скрытой переменной с именем this.

Ну или представьте другой случай: в программе еще не создан ни один объект нашего класса. Статический метод класса можно вызвать? Да. А сможет этот статический метод вызвать обычный метод?

И у какого объекта он его вызовет? Ведь еще не существует ни одного экземпляра нашего класса!

Может вызывать статические методы класса

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

Может обращаться к обычным переменным класса

Из обычного метода можно обращаться к обычным переменным класса, т.к. при этом произойдет обращение к переменным экземпляра класса, который легко получить из скрытого параметра this.

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

Поэтому статические методы не могут обращаться к обычным переменным класса.

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

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

Неизвестно! Поэтому и нельзя вызывать обычный метод из статического, не указывая ссылку на объект!

Может обращаться к статическим переменным класса

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

Может быть вызван у объекта

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

Код Как его видит компилятор
Thread th = Thread.current();
th.sleep(1000);
Thread th = Thread.current();
Thread.sleep(1000);
Integer i = 1;
int x = i.parseInt("12");
Integer i = 1;
int x = Integer.parseInt("12");
"".valueOf(12);
String.valueOf(12);

Может быть вызван у класса

У класса можно вызвать только статический метод, для вызова обычного метода нужна ссылка на экземпляр класса. Поэтому нельзя вызвать обычный метод конструкцией вида ИмяКласса.имяМетода(параметры)


undefined
13
Задача
Java Syntax Pro, 13 уровень, 1 лекция
Недоступна
Распаковка
В классе Solution представлены 8 объектов-оберток примитивных типов с именами вида типValueBox. Для каждого из этих объектов-оберток необходимо создать переменные соответствующего примитивного типа и присвоить им имена вида типValue. Для создания переменной используй метод объекта-обертки типValueBo
undefined
13
Задача
Java Syntax Pro, 13 уровень, 1 лекция
Недоступна
Сравнение чисел
В классе Solution есть три поля с одинаковыми значениями. В методе main происходит их сравнение с выводом результата в консоли. Добавь использование метода equals() в методе main такое минимальное количество раз, чтобы вывод был true true true