Ключевое слово var в Java: что, зачем и почему
Разбираемся, что за var такой и в каких ситуациях он может пригодиться.
robby mccullough / unsplash
Что случилось?
Начиная с версии 10, в Java появилось ключевое слово var. Новая фича — local variable type inference (выведение типа локальной переменной) — не даёт переменным дополнительных возможностей. Впрочем, и ограничений на них не накладывает. Просто разработчикам не нужно теперь писать лишний код при объявлении переменных, когда их тип очевиден из контекста.
В каких случаях тип переменной очевиден?
Если переменной сразу же присваивается значение, для которого компилятор может однозначно понять тип. Вот три типичных ситуации, когда удобно перейти от явного указания типа к var:
1. При создании нового экземпляра класса. Особенно если у этого класса длинное название.
В этом случае компилятор «догадывается», что у переменной theLongestNameYouCanEverImagine должен быть тип TheLongestNameYouCanEverImagine.
2. В заголовке цикла.
Здесь переменной i неявно устанавливается тип int.
Если инициализировать переменную целым числом, то по умолчанию для неё будет определён тип int. Чтобы компилятор решил иначе, нужны подсказки-постфиксы: L — для типа long, F — для float, D — для double, или явное приведение к другому типу.
3. В блоке try-with-resources.
Тут в заголовке блока инициализируются две локальные переменные: у reader будет тип BufferedReader, у writer — BufferedWriter.
Присвоить значение сразу же означает, что нельзя сначала просто дать var-переменной имя и только следующим оператором инициализировать её:
А ещё важно не перепутать окончание оператора с концом строки. Операторы в Java не прерываются переносами строк, поэтому разрешается объявлять переменную в нескольких строках:
Можно ли для любой переменной не указывать тип, если мы сразу её инициализируем?
Нет. На это намекает первая часть названия фичи — local variable. Ключевое слово var можно использовать только с локальными переменными, то есть переменными, которые объявлены:
- внутри конструкторов;
- внутри блоков инициализации;
- внутри методов.
Например:
Новый метод объявления неприменим к переменным экземпляра (instance variable) и переменным класса (статическим переменным). То есть вот такие строчки кода компилятор сочтёт ошибочными:
Не путайте переменные, объявленные внутри методов, и переменные — параметры методов. С первыми var использовать можно, со вторыми — нельзя.
Можно ли инициализировать значением null?
И да, и нет. Сам по себе null не даёт компилятору никакой информации о типе — ведь такое значение может быть у любого ссылочного типа. Лучшее, что мог бы сделать компилятор в такой ситуации, — это посчитать, что новая переменная имеет тип Object. Но программистам-то обычно нужно что-то более конкретное, чем Object, — у этого типа не так уж много полезных свойств и методов, так что архитекторы Java решили, что лучше null при использовании с var просто запретить.
Поэтому строка ниже не скомпилируется:
Но можно оставить подсказку компилятору:
И это объявление уже допустимо. Правда, не очень понятно, зачем так делать, — проще сразу явно указать тип.
А если с помощью var объявить сразу несколько переменных?
Нет, так не работает. Это просто нужно запомнить: var можно использовать только с одной новой переменной за раз. А вот так нельзя:
Хочу изменить для var-переменной первоначально заданное значение. Это разрешено?
Да пожалуйста! При объявлении задаётся только начальное значение, и менять его никто не запрещает:
Есть нюанс: ключевое слово var не отменяет правила для переменных с модификатором final. Значения final-переменных, даже введённых новомодным var, менять по-прежнему нельзя.
И тип тоже можно менять?
А вот и нет. Сэкономить на названиях переменных и переиспользовать одну и ту же локальную переменную с разными типами данных не выйдет. Но самим помнить о том, у какой переменной какой тип, не придётся. У компилятора память всё равно лучше, так что он просто не позволит вам совершить такого рода ошибку:
Не путайте Java с JavaScript: в языке JavaScript тоже есть ключевое слово var. И оно тоже используется для объявления переменных.
Только JavaScript не так строг к типам, как Java. Так что можно, например, присвоить переменной строковое значение, а через пару строчек кода — числовое.
В старом проекте есть переменная с именем var. Придётся ли её переименовывать, если я захочу перейти на десятую Java?
Не придётся, потому что var — это не зарезервированное слово. Оно может использоваться в качестве имени переменной или даже пакета. Вот так:
Правда, это не отменяет тот факт, что var — не лучшее имя для переменной. Оно не очень-то, а точнее, совсем не информативно.
Это ещё хорошо, что у вас в проекте никто не догадался так назвать класс, — вот его бы пришлось переименовывать с переходом к Java 10. Слово var нельзя использовать для именования нового типа — так не получится назвать класс, интерфейс или перечисление (enum).
Подытожим
- Ключевое слово var можно использовать при объявлении локальных переменных в конструкторах, блоках инициализации, методах.
- С ним не получится объявить параметры метода, переменные экземпляра или переменные класса.
- var нужно инициализировать сразу после именования — в одном операторе. При этом можно переносить такое объявление переменной на разные строки.
- Объявлять сразу несколько переменных с помощью var в одном операторе нельзя.
- Инициализировать var-переменную значением null без явного указания типа тоже нельзя.
- Значение var-переменной в дальнейшем меняться может, а вот тип — нет.
- var допустимо использовать в качестве названия переменной, но нельзя так именовать тип: класс, интерфейс или перечисление.
Чтобы ещё лучше разобраться с var, изучите это руководство. В нём собраны советы по использованию local variable type inference «из первых рук» — от сотрудника Oracle.
А если хотите больше узнать о языке Java в целом, приходите на наш курс «Профессия Java-разработчик». Вы научитесь программировать на самом востребованном языке, а мы поможем с трудоустройством.