JavaRush /Курсы /Java Syntax Pro /Статические методы

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

Java Syntax Pro
12 уровень , 3 лекция
Открыта

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)

12
Задача
Java Syntax Pro, 12 уровень, 3 лекция
Недоступна
Конвертер строки
В методе main конвертируй строку string в тип double с помощью статического метода parseDouble класса Double. Затем округли полученное значение, используя статический метод round класса Math. Результат выведи на экран.

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);

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

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


12
Задача
Java Syntax Pro, 12 уровень, 3 лекция
Недоступна
Оконные работы
В классе Window есть метод changeSize, который должен менять размеры окна на значения, переданные в метод. Но если ты запустишь программу, то убедишься, что этот метод не работает. Тебе нужно исправить ошибки так, чтобы метод заработал.
12
Задача
Java Syntax Pro, 12 уровень, 3 лекция
Недоступна
Одинаковые машины
В далеком-далеком прошлом все машины называли одинаково. Но вот в один прекрасный день директору завода по производству автомобилей надоело однообразие, и он выдал распоряжение: давать разные названия моделям авто. Итак, как ты уже догадался, твоя задача — помочь главному инженеру исправить программ
Комментарии (379)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
VadChet Уровень 28
12 мая 2025
Получается, что названия Статик и не-Статик не совсем подходящие. Думаю, лучше подойдут Классовый (или Общий) и Объектный (Частный). Общий - один для всех. Частный - у каждого свой.
Андрей Уровень 15
30 апреля 2025

и из статического метода нельзя вызвать нестатический: ссылку на экземпляр класса попросту неоткуда взять.
Вообще то можно. Если я в статический метод передам ссылку на объект и уже с ней вызову нестатический метод - это сработает.
8 мая 2025
Мне кажется тут и имеется ввиду, то что если вызвать ее без ссылки на объект
Андрей Уровень 15
14 мая 2025
Да, этот момент указан в конце лекции, я раньше времени написал
6 апреля 2025
Очень сильно запутали, лекции, конечно, супер, но тот, кто не знает о static, первое время точно встанет в ступор. Попробую объяснить проще и понятнее. В Java модификатором static можно помечать: -переменные; -методы; -внутренние классы. Всё, что помечено модификатором static, принадлежит не объектам (экземплярам класса), а самому классу. Например, мы создали класс Car: При создании новых объектов класса Car (new Car()), переменные power, year и brand будут уникальными для каждого объекта, а вот статическая переменная countAuto будет общей для всех объектов, и не создается заново при создании каждого экземпляра. Пример того, как можно использовать статическую переменную для подсчёта количества созданных объектов: Что происходит в примере выше: Каждый раз, когда создается новый объект класса Car, срабатывает конструктор, который увеличивает значение общей статической переменной countAuto на единицу. В конце мы получаем общее количество созданных объектов, обращаясь к статической переменной напрямую через имя класса (Car.countAuto).
Cryptosin Уровень 21
6 января 2025
Советую читать с приложения на телефоне все лекции. А потом с пк уже более вдумчиво повторять. Результат точно есть) вижу по себе
hjh Уровень 14
5 марта 2025
у меня и только через телефон норм получается, но попробую как вы сказали
JaCat Уровень 16
2 января 2025
На самом деле, если очень хочется вызывать нестатический метод внутри статического, то это можно устроить:

public class Demo {
    public int value = 100;
    public static int svalue = 200;

    public int plusVal(int i){
        int result = value + i;
        return result;
    }

    public static int staticPlusVal(int i){
        Demo obj = new Demo();
        return obj.plusVal(i);
    }
}
И вызывать соответственно можно через класс Demo.staticPlusVal(30);
Cryptosin Уровень 21
6 января 2025
Просто надо читать внимательно. В лекции же написано "Поэтому и нельзя вызывать обычный метод из статического, не указывая ссылку на объект!". "...не указывая ссылку на объект!!!" Что у тебя и происходит. Ты вызываешь через ссылку на объект, а не через класс. Никаких противоречий нет.
Кирилл Уровень 1
30 декабря 2024
как не интересно чтож такое почему каждый урок мы не учимся писать программу
Yasin Akhmadov Уровень 21
29 декабря 2024
Теперь понятно. Весь юмор заключается в том, что в статических методах просто отсутствует ключевое слово this, а ведь оно указывает ссылку переменной или метода на объект. Допустим, в статическом методе мы не сможем вызвать или использовать какое-нибудь обычное поле класса или его обычный метод, потому что эта переменная или метод ни на что не ссылаются (нет this). Например потом мы в методе main создали объект этого класса, и если мы захотим потом использовать этот static метод, то объект не поймёт его ли поля в этом методе используются, ведь в этом статик методе нет this, а значит все поля и методы использованные в этом static методе попросту не ссылаются на этот объект и выходит ошибка компиляции.
IWan Уровень 16
22 ноября 2024
При загрузки класса в память - создаётся 2 объекта. Один из них - статический, где находятся все статические челны класса. Так а если в классе не было статических элементов (никаких полей и методов). Будет ли создан статический объект ?
марк Уровень 25
27 декабря 2024
Да, об этом говорилось в предыдущих темах. Не скажу в какой точно, но на этом уровне.
Anton Zhukov Уровень 1
1 марта 2025
Тут в первом абзаце - https://javarush.com/quests/lectures/questsyntaxpro.level11.lecture01
NightCrow Уровень 27
14 сентября 2024
Лектору надо быть как то аккуратнее в утверждениях и указывать условия, при которых его утверждения верны. Ну вот я вызываю нестатический метод из статического. И ссылку, которую якобы неоткуда взять, сам и создаю. Ну и? public class NotStaticFromStatic { public int notMain() { return 1; } public static void main(String[] args) { NotStaticFromStatic nonStaticFromStatic = new NotStaticFromStatic(); System.out.println("Результат: "+nonStaticFromStatic.notMain()); } } Результат: 1
Andrey Shepel Уровень 23
2 октября 2024
Вы вызываете не статический метод notMain у экземпляра класса NotStaticFromStatic, где здесь противоречие? Имеется ввиду что вы не можете сделать так: NotStaticFromStatic.notMain(); Или так: public static void main(String[] args) { System.out.println(this.notMain()); } Как по мне все логично из утверждений лектора)
improvement Уровень 14
2 сентября 2024

Path path = Path.of("c:\\readme.txt");

Thread th = Thread.current();
Как это работает? Это не вызов конструктора и не метод который что-то возвращает. Что это вообще? Или там в методе создается новый экземпляр класса Path / Thread с параметрами?
Max_None Уровень 11
16 декабря 2024
Это так называемые "фабричные" методы, они возвращают ссылку на новый созданный объект. В первом случае статический метод класса Path создает экземпляр Path на основе пути, переданного в качестве параметра. Информации в сети очень много по фабричным методам. Почитай, они часто используются.
Юрий Болотин Уровень 16
23 марта 2025
Path.of() - статический метод, который возвращает ссылку на новый созданный объект. Примеры:

Path file = Path.of("c:\\projects\\note.txt"); // путь к файлу; 
Path directory = Path.of("c:\\projects\\");   // путь к директории

/* Объект типа Path — это как продвинутая версия типа String, он не привязан 
к конкретному файлу на диске: он просто хранит некий путь на диске. */
Что касается current... Предполагаю, что имелся в виду статический метод currentThread(), поскольку в документации отсутствует метод current.

public static Thread currentThread()
// Returns the Thread object for the current thread.
/* Returns:
the current thread */