Устаревшее ключевое слово «var»
Информация, приведенная в этой статье, полезна для понимания старых скриптов.
Мы не пишем современный код таким образом.
В самой первой главе про переменные мы ознакомились с тремя способами объявления переменных:
let и const ведут себя одинаково по отношению к лексическому окружению, области видимости.
Но var – это совершенно другой зверь, берущий своё начало с давних времён. Обычно var не используется в современных скриптах, но всё ещё может скрываться в старых.
Если в данный момент вы не работаете с подобными скриптами, вы можете пропустить или отложить прочтение данной главы, однако, есть шанс, что вы столкнётесь с var в будущем.
На первый взгляд, поведение var похоже на let . Например, объявление переменной:
function sayHi() < var phrase = "Привет"; // локальная переменная, "var" вместо "let" alert(phrase); // Привет >sayHi(); alert(phrase); // Ошибка: phrase не определена
…Однако, отличия всё же есть.
Для «var» не существует блочной области видимости
Область видимости переменных var ограничивается либо функцией, либо, если переменная глобальная, то скриптом. Такие переменные доступны за пределами блока.
if (true) < var test = true; // используем var вместо let >alert(test); // true, переменная существует вне блока if
Так как var игнорирует блоки, мы получили глобальную переменную test .
А если бы мы использовали let test вместо var test , тогда переменная была бы видна только внутри if :
if (true) < let test = true; // используем let >alert(test); // Error: test is not defined
Аналогично для циклов: var не может быть блочной или локальной внутри цикла:
for (var i = 0; i < 10; i++) < // . >alert(i); // 10, переменная i доступна вне цикла, т.к. является глобальной переменной
Если блок кода находится внутри функции, то var становится локальной переменной в этой функции:
function sayHi() < if (true) < var phrase = "Привет"; >alert(phrase); // срабатывает и выводит "Привет" > sayHi(); alert(phrase); // Ошибка: phrase не определена (видна в консоли разработчика)
Как мы видим, var выходит за пределы блоков if , for и подобных. Это происходит потому, что на заре развития JavaScript блоки кода не имели лексического окружения. Поэтому можно сказать, что var – это пережиток прошлого.
«var» допускает повторное объявление
Если в блоке кода дважды объявить одну и ту же переменную let , будет ошибка:
let user; let user; // SyntaxError: 'user' has already been declared
Используя var , можно переобъявлять переменную сколько угодно раз. Повторные var игнорируются:
var user = "Pete"; var user; // ничего не делает, переменная объявлена раньше // . нет ошибки alert(user); // Pete
Если дополнительно присвоить значение, то переменная примет новое значение:
var user = "Pete"; var user = "John"; alert(user); // John
«var» обрабатываются в начале запуска функции
Объявления переменных var обрабатываются в начале выполнения функции (или запуска скрипта, если переменная является глобальной).
Другими словами, переменные var считаются объявленными с самого начала исполнения функции вне зависимости от того, в каком месте функции реально находятся их объявления (при условии, что они не находятся во вложенной функции).
function sayHi() < phrase = "Привет"; alert(phrase); var phrase; >sayHi();
…Технически полностью эквивалентен следующему (объявление переменной var phrase перемещено в начало функции):
function sayHi() < var phrase; phrase = "Привет"; alert(phrase); >sayHi();
…И даже коду ниже (как вы помните, блочная область видимости игнорируется):
function sayHi() < phrase = "Привет"; // (*) if (false) < var phrase; >alert(phrase); > sayHi();
Это поведение называется «hoisting» (всплытие, поднятие), потому что все объявления переменных var «всплывают» в самый верх функции.
В примере выше if (false) условие никогда не выполнится. Но это никаким образом не препятствует созданию переменной var phrase , которая находится внутри него, поскольку объявления var «всплывают» в начало функции. Т.е. в момент присвоения значения (*) переменная уже существует.
Объявления переменных «всплывают», но присваивания значений – нет.
Это проще всего продемонстрировать на примере:
function sayHi() < alert(phrase); var phrase = "Привет"; >sayHi();
Строка var phrase = «Привет» состоит из двух действий:
- Объявление переменной var
- Присвоение значения в переменную = .
Объявление переменной обрабатывается в начале выполнения функции («всплывает»), однако присвоение значения всегда происходит в той строке кода, где оно указано. Т.е. код выполняется по следующему сценарию:
function sayHi() < var phrase; // объявление переменной срабатывает вначале. alert(phrase); // undefined phrase = "Привет"; // . присвоение - в момент, когда исполнится данная строка кода. >sayHi();
Поскольку все объявления переменных var обрабатываются в начале функции, мы можем ссылаться на них в любом месте. Однако, переменные имеют значение undefined до строки с присвоением значения.
В обоих примерах выше вызов alert происходил без ошибки, потому что переменная phrase уже существовала. Но её значение ещё не было присвоено, поэтому мы получали undefined .
IIFE
В прошлом, поскольку существовал только var , а он не имел блочной области видимости, программисты придумали способ её эмулировать. Этот способ получил название «Immediately-invoked function expressions» (сокращенно IIFE).
Это не то, что мы должны использовать сегодня, но, так как вы можете встретить это в старых скриптах, полезно понимать принцип работы.
IIFE выглядит следующим образом:
(function() < var message = "Hello"; alert(message); // Hello >)();
Здесь создаётся и немедленно вызывается Function Expression. Так что код выполняется сразу же и у него есть свои локальные переменные.
Function Expression обёрнуто в скобки (function <. >) , потому что, когда JavaScript встречает «function» в основном потоке кода, он воспринимает это как начало Function Declaration. Но у Function Declaration должно быть имя, так что такой код вызовет ошибку:
// Пробуем объявить и сразу же вызвать функцию function() < // ();
Даже если мы скажем: «хорошо, давайте добавим имя», – это не сработает, потому что JavaScript не позволяет вызывать Function Declaration немедленно.
// ошибка синтаксиса из-за скобок ниже function go() < >(); //
Так что скобки вокруг функции – это трюк, который позволяет объяснить JavaScript, что функция была создана в контексте другого выражения, а значит, что это Function Expression: ей не нужно имя и её можно вызвать немедленно.
Помимо круглых скобок существуют и другие способы сообщить JavaScript, что мы имеем в виду Function Expression:
// Способы создания IIFE (function() < alert("Круглые скобки вокруг функции"); >)(); (function() < alert("Круглые скобки вокруг всего выражения"); >()); !function() < alert("Выражение начинается с логического оператора НЕ"); >(); +function() < alert("Выражение начинается с унарного плюса"); >();
Во всех перечисленных случаях мы объявляем Function Expression и немедленно запускаем его. Ещё раз отметим: в настоящее время необходимости писать подобный код нет.
Итого
Существует 2 основных отличия var от let/const :
- Переменные var не имеют блочной области видимости, они ограничены, как минимум, телом функции.
- Объявления (инициализация) переменных var производится в начале исполнения функции (или скрипта для глобальных переменных).
Есть ещё одно небольшое отличие, относящееся к глобальному объекту, мы рассмотрим его в следующей главе.
Эти особенности, как правило, не очень хорошо влияют на код. Блочная область видимости – это удобно. Поэтому много лет назад let и const были введены в стандарт и сейчас являются основным способом объявления переменных.
Var java что это
Для хранения данных в программе предназначены переменные . Переменная представляет именованную область памяти, которая хранит значение определенного типа. Каждая переменная имеет тип, имя и значение. Тип определяет, какую информацию может хранить переменная или диапазон допустимых значений.
Переменные объявляются следующим образом:
тип_данных имя_переменной;
Например, определим переменную, которая будет называться x и будет иметь тип int :
int x;
В этом выражении мы объявляем переменную x типа int . То есть x будет хранить некоторое число не больше 4 байт.
В качестве имени переменной может выступать любое произвольное название, которое удовлетворяет следующим требованиям:
- имя может содержать любые алфавитно-цифровые символы, а также знак подчеркивания, при этом первый символ в имени не должен быть цифрой
- в имени не должно быть знаков пунктуации и пробелов
- имя не может быть ключевым словом языка Java
Кроме того, при объявлении и последующем использовании надо учитывать, что Java - регистрозависимый язык, поэтому следующие объявления int num; и int NUM; будут представлять две разных переменных.
Объявив переменную, мы можем присвоить ей значение:
int x; // объявление переменной x = 10; // присвоение значения System.out.println(x); // 10
Также можно присвоить значение переменной при ее объявлении. Этот процесс называется инициализацией :
int x = 10; // объявление и инициализация переменной System.out.println(x); // 10
Если мы не присвоим переменной значение до ее использования, то мы можем получить ошибку, например, в следующем случае:
int x; System.out.println(x);
Через запятую можно объявить сразу несколько переменных одного типа:
int x, y; x = 10; y = 25; System.out.println(x); // 10 System.out.println(y); // 25
Также можно их сразу инициализировать:
int x = 8, y = 15; System.out.println(x); // 8 System.out.println(y); // 15
Отличительной особенностью переменных является то, что мы можем в процессе работы программы изменять их значение:
int x = 10; System.out.println(x); // 10 x = 25; System.out.println(x); // 25
Ключевое слово var
Начиная с Java 10 в язык было добавлено ключевое слово var , которое также позволяет определять переменную:
var x = 10; System.out.println(x); // 10
Слово var ставится вместо типа данных, а сам тип переменной выводится из того значения, которое ей присваивается. Например, переменной x присваивается число 10, значит, переменная будет представлять тип int.
Но если переменная объявляется с помощью var, то мы обязательно должны инициализировать ее, то есть предоставить ей начальное значение, иначе мы получим ошибку, как, например, в следующем случае:
var x; // ! Ошибка, переменная не инициализирована x = 10;
Константы
Кроме переменных, в Java для хранения данных можно использовать константы . В отличие от переменных константам можно присвоить значение только один раз. Константа объявляется также, как и переменная, только вначале идет ключевое слово final :
final int LIMIT = 5; System.out.println(LIMIT); // 5 // LIMIT=57; // так мы уже не можем написать, так как LIMIT - константа
Как правило, константы имеют имена в верхнем регистре.
Константы позволяют задать такие переменные, которые не должны больше изменяться. Например, если у нас есть переменная для хранения числа pi, то мы можем объявить ее константой, так как ее значение постоянно.
Var java что это
Оператор var объявляет переменную, инициализируя её, при необходимости.
Интерактивный пример
Синтаксис
var varname1 [= value1 [, varname2 [, varname3 . [, varnameN]]]];
Имя переменной. Может использоваться любой допустимый идентификатор.
Значение переменной. Любое допустимое выражение. По умолчанию значение undefined.
Описание
Объявление переменной всегда обрабатывается до выполнения кода, где бы она ни находилась. Область видимости переменной, объявленной через var , это её текущий контекст выполнения. Который может ограничиваться функцией или быть глобальным, для переменных, объявленных за пределами функции.
Присвоение значения необъявленной переменной подразумевает, что она будет создана как глобальная переменная (переменная становится свойством глобального объекта) после выполнения присваивания значения. Различия между объявленной и необъявленной переменными следующие:
1. Объявленные переменные ограничены контекстом выполнения, в котором они были объявлены. Необъявленные переменные всегда глобальны.
function x() y = 1; // возбудит ReferenceError в "строгом режиме" var z = 2; > x(); console.log(y); // выведет "1" console.log(z); // возбудит ReferenceError: z не определён вне x
2. Объявленные переменные инициализируются до выполнения любого кода. Необъявленные переменные не существуют до тех пор, пока к ним не выполнено присваивание.
.log(a); // Возбудит ReferenceError. console.log("still going. "); // Не выполнится.
var a; console.log(a); // Выведет "undefined" или "", в зависимости от браузера. console.log("still going. "); // Выведет "still going. ".
3. Объявленные переменные, независимо от контекста выполнения, являются ненастраиваемыми свойствами. Необъявленные переменные это настраиваемые свойства (т.е. их можно удалять).
var a = 1; b = 2; delete this.a; // Возбудит TypeError в "строгом режиме". В "нестрогом режиме" будет ошибка без уведомления. delete this.b; console.log(a, b); // Возбудит ReferenceError. // Свойство 'b' было удалено и больше не существует.
Из-за перечисленных различий, использование необъявленных переменных может привести к непредсказуемым последствиям. Рекомендовано всегда объявлять переменные, вне зависимости, находятся они внутри функции или в глобальном контексте. Присваивание значения необъявленной переменной в строгом режиме (en-US) ECMAScript 5 возбуждает ошибку.
Поднятие переменных
Объявление переменных (как и любые другие объявления) обрабатываются до выполнения кода. Где бы не находилось объявление, это равнозначно тому, что переменную объявили в самом начале кода. Это значит, что переменная становится доступной до того, как она объявлена. Такое поведение называется "поднятием" (в некоторых источниках "всплытием").
= 2; var bla; // . // читается как: var bla; bla = 2;
Поэтому объявление переменных рекомендовано выносить в начало их области видимости (в начало глобального кода или в начало функции). Это даёт понять какие переменные принадлежат функции (т.е. являются локальными), а какие обрабатываются в цепи областей видимости (т.е. являются глобальными).
Важно отметить, что подъем будет влиять на объявление переменной, но не на инициализацию её значения. Значение присваивается при выполнении оператора присваивания:
function do_something() console.log(bar); // выведет undefined var bar = 111; console.log(bar); // выведет 111 > // . неявно понимается как: function do_something() var bar; console.log(bar); // выведет undefined bar = 111; console.log(bar); // выведет 111 >
Первый контакт с «var» в Java 10

Java 10 будет выпущен 20 марта 2018 года, и все фичи, которые должны быть в этом релизе, уже объединены в основную ветку разработки. Одним из самых интересных нововведений Java 10 безусловно является вывод типа локальной переменной (JEP 286). Это дает вам возможность сократить объявления переменных используя новое ключевое слово var:
var users = new ArrayList();
И это все, спасибо за внимание!
Нет, я уверен, что вам интересно узнать больше. Под катом я расскажу, где применяется var, а где нет, как это влияет на читаемость кода и что произошло с val.
Замена объявлений типа с помощью var
В качестве разработчика Java мы привыкли дважды вводить типы, один раз для объявления переменной и второй раз для следующего за ней конструктора:
URL codefx = new URL("http://codefx.org");
Мы также часто объявляем типы переменных, которые используются только один раз:
URL codefx = new URL("http://codefx.org"); URLConnection connection = codefx.openConnection(); Reader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()));
Это не особенно страшно, но всё же несколько избыточно. И хотя IDE могут помочь в написании такого кода, читаемость страдает, когда имена переменных перескакивают вправо-влево, потому что названия типов имеют разную длину или когда разработчики избегают объявления промежуточных переменных, потому что объявления типов будут отвлекать на себя много внимания, не принося никакой пользы.
Начиная с Java 10 у разработчиков появится альтернатива — они могут позволить компилятору вывести тип с помощью var:
var codefx = new URL("http://codefx.org"); var connection = codefx.openConnection(); var reader = new BufferedReader( new InputStreamReader(connection.getInputStream()));
При обработке var, компилятор просматривает правую часть объявления, так называемый инициализатор и использует его тип для переменной. И это нужно не только для внутренних расчётов, полученный тип будет также записан в итоговый байт-код.
Как вы видите, это экономит несколько символов при наборе текста, но, что более важно, он дедуплицирует избыточную информацию и аккуратно выравнивает имена переменных, что облегчает их чтение. Стоимость очевидна: некоторые типы переменных, например connection, не сразу очевидны. IDE могут, конечно же, показывать их по требованию, но это не помогает ни в какой другой среде (например, при просмотре кода в браузере — на stackoverflow или даже в этой статье — прим. перев.).
Кстати, если вы беспокоитесь о конфликтах с методами и переменными с именем var: не нужно. Технически, var — это не ключевое слово, а зарезервированное имя типа, то есть его можно использовать только в тех местах, где компилятор ожидает имя типа, но во всех остальных местах он является допустимым идентификатором. Это означает, что только классы, называемые var, больше не будут работать, но это не особо частый случай.
Вывод типа локальной переменной выглядит как простая функция, но это обманчиво. Возможно, у вас уже есть некоторые вопросы:
- хм, это Java или JavaScript?
- где я могу это использовать?
- не ухудшится ли читаемость кода?
- почему не val или let?
Нет, это не JavaScript
Я хочу начать с подчеркивания того, что var не изменяет приверженность Java статической типизации ни на йоту. Компилятор отображает все задействованные типы и помещает их в файлы классов, как если бы вы их вводили сами.
Например, вот результат декомпиляции IntelliJ (фактически Fernflower) файла класса с примером URL:
URL codefx = new URL("http://codefx.org"); URLConnection connection = codefx.openConnection(); BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()));
Это байт в байт тот же результат, как если бы я сам объявил типы. Фактически вывод типов существует только во время компиляции и никак не влияет на итоговый байт-код, что также означает отсутствие какого-либо влияния на производительность. Так что расслабьтесь, это не Javascript, и никто не собирается превращать 0 в бога.
Если вы все еще обеспокоены тем, что отсутствие явных типов делает код хуже, у меня есть вопрос для вас: вы когда-нибудь писали лямбда-выражения, не определяя типы аргументов?
rhetoricalQuestion.answer(yes -> "уловили мысль?");
Где использовать var (и где не нужно)
Название JEP 286, «вывод типа локальной переменной», немного намекает на то, где var можно использовать: для локальных переменных. Точнее, для «локальных объявлений переменных с инициализаторами», так что следующий код работать не будет:
// неа var foo; foo = "Foo";
Код должен быть таким: var foo = ''Foo''. Даже тогда это распространяется не на все случаи, так как var не будет работать с так называемыми «poly expressions», такими как лямбда-выражения и ссылки на методы, тип которых компилятор определяет в отношении ожидаемого типа:
// ничто из этого не работает var ints = ; var appendSpace = a -> a + " "; var compareString = String::compareTo
Единственное подходящее место, помимо локальных переменных — это цикл for:
var numbers = List.of("a", "b", "c"); for (var nr : numbers) System.out.print(nr + " "); for (var i = 0; i < numbers.size(); i++) System.out.print(numbers.get(i) + " ");
Это означает, что поля, сигнатуры методов и выражения catch все еще требуют ручного объявления типа.
// неа private var getFoo()
Устранение ошибок «Действие на расстоянии»
То, что var может использоваться только локально, является не техническим ограничением, а конструктивным решением. Конечно, было бы неплохо, если бы он работал так:
// держим кулачки за то, чтобы компилятор вывел List var users = new ArrayList(); // но нет, здесь ошибка компиляции: users = new LinkedList<>();
Компилятор мог бы легко просмотреть все присвоения и вывести наиболее конкретный тип, который подходит для каждого из них, но он не делает этого. Команда JDK хотела избежать ошибок «действия на расстоянии», что означает, что изменение кода в некотором месте не должно приводить к, казалось бы, несвязанной ошибке далеко в другой части системы.
В качестве примера рассмотрим следующее:
// выведено как `int` var (id < 100) < // очень длинная ветвь // к сожалению не имеет собственного метода >else < // ох, ещё больше кода. >
Пока что всё идёт… Я не хочу говорить «хорошо», но вы знаете, что я имею в виду. Я уверен, что вы видели такой код. Теперь добавим эту строку:
id = "124"
Что произойдет? Это не риторический вопрос, подумайте об этом.
Ответ заключается в том, что if-условие вызывает ошибку, потому что id больше не будет int и поэтому не может сравниться с 100. Эта ошибка находится на довольно большом расстоянии от изменения, вызвавшего ее. Кроме того, это непредвиденное следствие простого присваивания значения переменной.
С этой точки зрения, решение ограничить вывод типа до непосредственного объявления имеет смысл.
Почему не могут быть выведены типы полей и методов?
Поля и методы имеют гораздо большую область видимости, чем локальные переменные, и поэтому расстояние между изменениями и ошибками значительно возрастает. В худшем случае изменение типа параметра метода может привести к двоичной несовместимости и, следовательно, ошибкам времени выполнения. Это довольно экстремальное следствие изменения некоторых деталей реализации.
Так как не приватные поля и методы становятся частью контракта класса, и поскольку они не должны просто так меняться, их типы не выводятся. Конечно, исключение можно было бы сделать для приватных полей или методов, но это сделало бы вывод типов довольно запутанным.
Основная идея заключается в том, что локальные переменные являются деталями реализации и не могут ссылаться на «далекий» код, что уменьшает необходимость строгого, явного и подробного определения их типа.
Предпосылки появления var
Давайте посмотрим за кулисы и узнаем, почему был введен var, как он должен повлиять на читаемость и почему нет val (или let), сопровождающего его. Если вас интересует наиболее подробная информация, посмотрите дискуссии JEP 286, часто задаваемые вопросы и список рассылки Project Amber.
Но зачем?!
Java склонна быть довольно многословной, особенно по сравнению с более молодыми языками, это является одним из слабых мест языка и общей темой для критики новичками и опытными разработчиками Java. Project Amber, в рамках которого был разработан var, направлен на «изучение и инкубацию небольших, ориентированных на продуктивность разработки функций Java-языка», и цель состоит в том, чтобы в целом сократить рутину, связанную с написанием и чтением кода на Java.
Вывод типа локальной переменной согласуется с этой целью. С точки зрения написания кода, это явно упрощает объявление переменных, хотя я бы предположил, что добрая половина моих объявлений генерируется средой IDE, либо во время рефакторинга, либо потому что проще написать вызов конструктора или метода, а затем создать для него переменную.
Помимо упрощения объявлений это также делает их более податливыми. Что я имею в виду? Объявления могут быть довольно уродливыми, особенно если речь идет о названиях обобщённых классов в корпоративных приложениях.
InternationalCustomerOrderProcessor> orderProcessor = createInternationalOrderProcessor(customer, order);
Это чертовски длинное имя типа, которое выталкивает имя переменной в конец и оставляет вас либо с растянутой до 150 символов строкой, либо инициализацией переменной в новой строке. Оба варианта отстой, если вы нацелены на удобочитаемость.
var orderProcessor = createInternationalOrderProcessor(customer, order);
С var это гораздо менее обременительное и простое для глаз объявление промежуточных переменных, и мы могли бы сделать это в тех местах, где раньше не делали. Подумайте о вложенных или последовательных выражениях, которые вы решили не разбивать, потому что уменьшение их сложности компенсировалось увеличением числа рутинных действий. Разумное использование var может сделать промежуточные результаты более очевидными и более доступными.
Короче говоря, var — это про сокращение многословия и рутины, а не об экономии символов.
А что относительно читаемости?
Теперь перейдем к читаемости. Несомненно, когда типы отсутствуют, читаемость должна ухудшиться, не так ли? Вообще говоря, да. Когда вы пытаетесь понять, как работает часть кода, типы являются важным компонентом. И даже если бы IDE разработали функции, позволяющие отображать все выведенные типы, это все равно было бы более косвенным, чем если бы они всегда присутствовали в исходнике.
Таким образом, var сразу приносит нам недостаток читаемости и должен компенсировать это. Один из способов — выравнивание имен переменных:
// с явными типами No no = new No(); AmountIncrease more = new BigDecimalAmountIncrease(); HorizontalConnection jumping = new HorizontalLinePositionConnection(); Variable variable = new Constant(5); List names = List.of("Max", "Maria"); // с выведенными типами var no = new No(); var more = new BigDecimalAmountIncrease(); var jumping = new HorizontalLinePositionConnection(); var variable = new Constant(5); var names = List.of("Max", "Maria");
Имена типов важны, но имена переменных могут быть важнее. Типы описывают общую концепцию в контексте всей экосистемы Java (для классов JDK), общий вариант использования (библиотека или фреймворк) или бизнес-домен (приложение) и, следовательно, всегда будут иметь общие имена. Переменные, с другой стороны, определены в конкретном и очень малом контексте, в котором их имя может быть очень точным.
С var имена переменных выходят на первый план и выделяются так, как раньше этого не делали, особенно если подсветка кода отмечает ключевое слово и, таким образом, позволяет инстинктивно игнорировать его. Я какое-то время проводил час или два в день, читая Kotlin, и я тут же привык к этому. Это может значительно улучшить читаемость.
Как говорилось выше, другое улучшение читаемости может происходить из-за того, что объявлено больше промежуточных переменных, поскольку это связано со снижением издержек при записи и чтении.
Поиск стиля
Разумеется, легко переборщить с var и получить код с бестолковыми именами переменных и без видимых типов. Мы должны, сообщество в целом и каждая команда в частности, придумать стиль, который соответствует нашим потребностям и балансирует между многословием и ясностью.
Брайан Гетц (Brian Goetz), архитектор языка Java в Oracle и ответственный за Project Amber, дал первую эвристику:
Используйте конструкцию var, когда она делает код более понятным и более кратким, и вы не теряете существенную информацию.
В связи с этим я надеюсь, что IDE не будут вообще предупреждать нас, если объявление типа может быть заменено на var. Это не универсальная конструкция, как лямбда-выражения.
Почему нет val/let?
Многие языки с var также предлагают дополнительное ключевое слово для неизменяемых переменных. Обычно это называется val, иногда let, но Java 10 не имеет ни того, ни другого, и вместо этого мы должны использовать final var. Вот несколько причин:
- неизменяемость важна, но для локальных переменных она важна в меньшей степени
- начиная с Java 8 у нас есть концепция эффективного final, уже и без того приближающая нас к неизменяемым локальным переменным
- там, где var получил всеобщее одобрение (74% категорически, 12% умеренно) ответная реакция как на var / val, так и на var / let была весьма неоднозначной
Чтож, возможно в будущем… До тех пор мы должны использовать final var.
Подводя итоги
При объявлении локальных переменных вы можете использовать var вместо имени класса или интерфейса, чтобы позволить компилятору вывести тип. Это работает только в том случае, если переменная немедленно инициализируется, например, как в var s = "". Индексы для циклов также могут быть объявлены с помощью var. Тип, выводимый компилятором, помещается в байт-код, поэтому во время выполнения ничего не меняется — Java все еще является статически типизированным языком.
Помимо локальных переменных, например в полях и сигнатурах методов, var не может применяться. Это было сделано, чтобы избежать ошибок «действия на расстоянии» и сохранить место использования выведенной переменной рядом с местом объявления, что смягчает опасения, связанные с читабельностью.
Хотя бездумное использование var может сделать код хуже, тем не менее это шанс для Java-разработчиков написать более читабельный код, найдя новый баланс между шумом объявлений и сложностью вложенных / последовательных выражений.