Ключевое слово var в Java: что, зачем и почему
2026-02-21 08:15 Diff

#База знаний

  • 16 июл 2021
  • 0

Разбираемся, что за var такой и в каких ситуациях он может пригодиться.

robby mccullough / unsplash

Фулстек-разработчик. Любимый стек: Java + Angular, но в хорошей компании готова писать хоть на языке Ада.

Начиная с версии 10, в Java появилось ключевое слово var. Новая фича — local variable type inference (выведение типа локальной переменной) — не даёт переменным дополнительных возможностей. Впрочем, и ограничений на них не накладывает. Просто разработчикам не нужно теперь писать лишний код при объявлении переменных, когда их тип очевиден из контекста.

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

1. При создании нового экземпляра класса. Особенно если у этого класса длинное название.

var theLongestNameYouCanEverImagine = new TheLongestNameYouCanEverImagine();

В этом случае компилятор «догадывается», что у переменной theLongestNameYouCanEverImagine должен быть тип TheLongestNameYouCanEverImagine.

2. В заголовке цикла.

for (var i = 1; i < 10; i++){ //здесь что-то интересное происходит }

Здесь переменной i неявно устанавливается тип int.

Если инициализировать переменную целым числом, то по умолчанию для неё будет определён тип int. Чтобы компилятор решил иначе, нужны подсказки-постфиксы: L — для типа long, F — для float, D — для double, или явное приведение к другому типу.

var a = 2; // тип переменной a — int var b = 2L; // тип переменной b — long var c = 2F; // тип переменной c — float var d = 2D; // тип переменной d — double var e = (short) 2; //тип переменной e — short

3. В блоке try-with-resources.

void copyFile(File src, File dest) throws IOException { try (var reader = new BufferedReader(new FileReader(src)); var writer = new BufferedWriter(new FileWriter(dest))) { String s; while ((s = reader.readLine()) != null) { writer.write(s); writer.newLine(); } } }

Тут в заголовке блока инициализируются две локальные переменные: у reader будет тип BufferedReader, у writer — BufferedWriter.

Присвоить значение сразу же означает, что нельзя сначала просто дать var-переменной имя и только следующим оператором инициализировать её:

var x; // не скомпилируется x = 3; // не скомпилируется

А ещё важно не перепутать окончание оператора с концом строки. Операторы в Java не прерываются переносами строк, поэтому разрешается объявлять переменную в нескольких строках:

var x = 3; // отлично скомпилируется

Нет. На это намекает первая часть названия фичи — local variable. Ключевое слово var можно использовать только с локальными переменными, то есть переменными, которые объявлены:

  • внутри конструкторов;
  • внутри блоков инициализации;
  • внутри методов.

Например:

public class VarExample { public VarExample() { // var в конструкторе var constructorVar = "constructorVar"; } { // var в блоке инициализации var initializerVar = "initializerVar"; } void methodExample() { // var в методе var methodVar = "methodVar"; } }

Новый метод объявления неприменим к переменным экземпляра (instance variable) и переменным класса (статическим переменным). То есть вот такие строчки кода компилятор сочтёт ошибочными:

public class VarExample { var instanceVar = "instanceVar"; // не скомпилируется static var staticVar = "staticVar"; // не скомпилируется }

Не путайте переменные, объявленные внутри методов, и переменные — параметры методов. С первыми var использовать можно, со вторыми — нельзя.

public int sum(var x, var y) { // не скомпилируется return x + y; } public int sum2and2() { // а так можно var x = 2; var y = 2; return x + y; }

И да, и нет. Сам по себе null не даёт компилятору никакой информации о типе — ведь такое значение может быть у любого ссылочного типа. Лучшее, что мог бы сделать компилятор в такой ситуации, — это посчитать, что новая переменная имеет тип Object. Но программистам-то обычно нужно что-то более конкретное, чем Object, — у этого типа не так уж много полезных свойств и методов, так что архитекторы Java решили, что лучше null при использовании с var просто запретить.

Поэтому строка ниже не скомпилируется:

var nullVar = null; // не скомпилируется

Но можно оставить подсказку компилятору:

var nullVar = (String) null;

И это объявление уже допустимо. Правда, не очень понятно, зачем так делать, — проще сразу явно указать тип.

Нет, так не работает. Это просто нужно запомнить: var можно использовать только с одной новой переменной за раз. А вот так нельзя:

int a, var b = 3; // не скомпилируется var a = 1, b = 2; // тоже не скомпилируется var a = 1, var b = 2; // и даже так не скомпилируется int a = 3, b = 2; // да-да, так всё ещё можно

Да пожалуйста! При объявлении задаётся только начальное значение, и менять его никто не запрещает:

var s = "first value"; s = "second value";

Есть нюанс: ключевое слово var не отменяет правила для переменных с модификатором final. Значения final-переменных, даже введённых новомодным var, менять по-прежнему нельзя.

final var s = "first value"; s = "second value"; // не-не-не, вы же не просто так дописали модификатор final

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

var s = "string value"; // объявили переменную с неявным типом String s = "another string value"; // присвоили другое строковое значение s = 100; // не скомпилируется: попытка присвоить строковой //переменной числовое значение

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

Только JavaScript не так строг к типам, как Java. Так что можно, например, присвоить переменной строковое значение, а через пару строчек кода — числовое.

Не придётся, потому что var — это не зарезервированное слово. Оно может использоваться в качестве имени переменной или даже пакета. Вот так:

var var = "var"; // так можно

Правда, это не отменяет тот факт, что var — не лучшее имя для переменной. Оно не очень-то, а точнее, совсем не информативно.

Это ещё хорошо, что у вас в проекте никто не догадался так назвать класс, — вот его бы пришлось переименовывать с переходом к Java 10. Слово var нельзя использовать для именования нового типа — так не получится назвать класс, интерфейс или перечисление (enum).

  1. Ключевое слово var можно использовать при объявлении локальных переменных в конструкторах, блоках инициализации, методах.
  2. С ним не получится объявить параметры метода, переменные экземпляра или переменные класса.
  3. var нужно инициализировать сразу после именования — в одном операторе. При этом можно переносить такое объявление переменной на разные строки.
  4. Объявлять сразу несколько переменных с помощью var в одном операторе нельзя.
  5. Инициализировать var-переменную значением null без явного указания типа тоже нельзя.
  6. Значение var-переменной в дальнейшем меняться может, а вот тип — нет.
  7. var допустимо использовать в качестве названия переменной, но нельзя так именовать тип: класс, интерфейс или перечисление.

Чтобы ещё лучше разобраться с var, изучите это руководство. В нём собраны советы по использованию local variable type inference «из первых рук» — от сотрудника Oracle.

А если хотите больше узнать о языке Java в целом, приходите на наш курс «Профессия Java-разработчик». Вы научитесь программировать на самом востребованном языке, а мы поможем с трудоустройством.

Научитесь: Профессия Java-разработчик + ИИ Узнать больше