Var in java?
If you are like me who picked up java when it was released a quarter of a century back, chances are that you will appreciate this.
The backend for one of our projects is in java and spring boot. As part of best practices of software development, we configured our code to be analysed by Sonarqube, an awesome tool for code quality.
As we looked at the different types of issues reported by the tool, we spotted this one
Declare this local variable with “var” instead.
Hey, was I reading this right? This is java code and not javascript, right? Even in javascript, we now should be using let and const to scope the variables correctly. var in java? On clicking the Why is this an issue? link, we were presented with more details.
Quoting from the details displayed by Sonarqube
Local-Variable Type Inference should be used
In Java 10 Local-Variable Type Inference was introduced. It allows you to omit the expected type of a variable by declaring it with the var keyword.
While it is not always possible or cleaner to use this new way of declaring a variable, when the type on the left is the same as the one on the right in an assignment, using the var will result in a more concise code.
This rule reports an issue when the expected type of the variable is the same as the returned type of assigned expression.
Boy, weren’t we glad we decided to use Java 11, rather than Java 8 to build this application? As you can see above, this feature came into Java in Java 10.
This is not the only thing that Sonarqube revealed. Another java language construct (from Java 8) is Optional . If you use recent versions of spring-boot, you will automatically use it (since the findById method returns an Optional )
Now how to initialize an Optional ?
was valid, think again. While there is no compilation (or runtime) errors, Sonarqube tells you
Replace this null literal by an “Optional” object
Again, quoting from their explanation
The concept of Optional is that it will be used when null could cause errors. In a way, it replaces null , and when Optional is in use, there should never be a question of returning or receiving null from a call.
Var java что это
In JDK 10 and later, you can declare local variables with non-null initializers with the var identifier, which can help you write code that’s easier to read.
Consider the following example, which seems redundant and is hard to read:
You can rewrite this example by declaring the local variables with the var identifier. The type of the variables are inferred from the context:
var is a reserved type name, not a keyword, which means that existing code that uses var as a variable, method, or package name is not affected. However, code that uses var as a class or interface name is affected and the class or interface needs to be renamed.
var can be used for the following types of variables:
Local variable declarations with initializers:
Enhanced for -loop indexes:
Index variables declared in traditional for loops:
try -with-resources variable:
Formal parameter declarations of implicitly typed lambda expressions: A lambda expression whose formal parameters have inferred types is implicitly typed :
In JDK 11 and later, you can declare each formal parameter of an implicitly typed lambda expression with the var identifier:
As a result, the syntax of a formal parameter declaration in an implicitly typed lambda expression is consistent with the syntax of a local variable declaration; applying the var identifier to each formal parameter in an implicitly typed lambda expression has the same effect as not using var at all.
You cannot mix inferred formal parameters and var -declared formal parameters in implicitly typed lambda expressions nor can you mix var -declared formal parameters and manifest types in explicitly typed lambda expressions. The following examples are not permitted:
Local Variable Type Inference Style Guidelines
Local variable declarations can make code more readable by eliminating redundant information. However, it can also make code less readable by omitting useful information. Consequently, use this feature with judgment; no strict rule exists about when it should and shouldn’t be used.
Local variable declarations don’t exist in isolation; the surrounding code can affect or even overwhelm the effects of var declarations. Style Guidelines for Local Variable Type Inference in Java examines the impact that surrounding code has on var declarations, explains tradeoffs between explicit and implicit type declarations, and provides guidelines for the effective use of var declarations.
Var java что это

Для хранения данных в программе предназначены переменные . Переменная представляет именованную область памяти, которая хранит значение определенного типа. Каждая переменная имеет тип, имя и значение. Тип определяет, какую информацию может хранить переменная или диапазон допустимых значений.
Переменные объявляются следующим образом:
Например, определим переменную, которая будет называться x и будет иметь тип int :
В этом выражении мы объявляем переменную x типа int . То есть x будет хранить некоторое число не больше 4 байт.
В качестве имени переменной может выступать любое произвольное название, которое удовлетворяет следующим требованиям:
имя может содержать любые алфавитно-цифровые символы, а также знак подчеркивания, при этом первый символ в имени не должен быть цифрой
в имени не должно быть знаков пунктуации и пробелов
имя не может быть ключевым словом языка Java
Кроме того, при объявлении и последующем использовании надо учитывать, что Java — регистрозависимый язык, поэтому следующие объявления int num; и int NUM; будут представлять две разных переменных.
Объявив переменную, мы можем присвоить ей значение:
Также можно присвоить значение переменной при ее объявлении. Этот процесс называется инициализацией :
Если мы не присвоим переменной значение до ее использования, то мы можем получить ошибку, например, в следующем случае:
Через запятую можно объявить сразу несколько переменных одного типа:
Также можно их сразу инициализировать:
Отличительной особенностью переменных является то, что мы можем в процессе работы программы изменять их значение:
Ключевое слово var
Начиная с Java 10 в язык было добавлено ключевое слово var , которое также позволяет определять переменную:
Слово var ставится вместо типа данных, а сам тип переменной выводится из того значения, которое ей присваивается. Например, переменной x присваивается число 10, значит, переменная будет представлять тип int.
Но если переменная объявляется с помощью var, то мы обязательно должны инициализировать ее, то есть предоставить ей начальное значение, иначе мы получим ошибку, как, например, в следующем случае:
Константы
Кроме переменных, в Java для хранения данных можно использовать константы . В отличие от переменных константам можно присвоить значение только один раз. Константа объявляется также, как и переменная, только вначале идет ключевое слово final :
Как правило, константы имеют имена в верхнем регистре.
Константы позволяют задать такие переменные, которые не должны больше изменяться. Например, если у нас есть переменная для хранения числа pi, то мы можем объявить ее константой, так как ее значение постоянно.
FAQ по var в Java

Локальные переменные — это «рабочие лошадки» Java. Они используются для хранения промежуточных результатов вычислений. И, в отличие от полей, объявляются, инициализируются и используются в одном блоке. Для понимания кода часто более важны имя и инициализатор, чем тип локальной переменной. В имени и инициализаторе столько же информации, сколько и в типе:
Вместо явного указания типа можно использовать var :
Компилятор определяет тип локальной переменной по инициализатору. Это особенно важно, когда тип параметризован wildcard , или упоминается в инициализаторе. Использование var может сделать код более кратким без ущерба для удобочитаемости, а в некоторых случаях может улучшить читаемость благодаря устранению избыточности.
Вопрос 2. Делает ли это Java динамически типизированным языком? Это то же самое, что и var в JavaScript?
Нет и нет. Java остается языком со статической типизацией, и появление var не изменяет этого. var используется в объявлении локальной переменной без явного указания типа. При использовании var компилятор Java определяет тип переменной во время компиляции, используя информацию о типе, полученную от инициализатора переменной. Далее выведенный тип используется как статический тип этой переменной. Как правило, будет тот же тип, который вы бы указали явно, поэтому переменная, объявленная с помощью var , ведет себя точно так же, как при явном указании типа.
В компиляторе Java выведение типов присутствует уже много лет. Например, параметры лямбда-выражения в Java 8 не нуждаются в явном указании типа, так как компилятор определяет их по тому, как используется лямбда-выражение:
В приведенном выше фрагменте кода тип параметра p в лямбде выводится как Person . Если класс Person будет изменен так, что в нем больше не будет метода getAge , или в списке будет храниться что-то отличное от Person , то выведение типа завершится ошибкой при компиляции.
Вопрос 3. Переменная var неявно final?
Нет. Локальные переменные, объявленные с помощью var , по умолчанию не являются final . Однако к var можно добавить модификатор final :
Для final var в Java нет никакого сокращения. Например, в Scala для объявления неизменяемых переменных используется val . В Scala это хорошо работает, потому что все переменные (и локальные, и поля) объявляются с помощью синтаксиса следующего вида.
Указывать » : type » в объявлении необязательно — это зависит от того, хотите ли вы использовать выведение типа или нет. В Scala выбор между изменяемостью и неизменяемостью ортогонален к выведению типов.
В Java var можно использовать только там, где требуется выведение типа. Его нельзя использовать, если тип объявлен явно. Если в Java добавить val , то его тоже можно было бы использовать только там, где используется выведение типов. В Java нельзя было бы использовать var или val для управления иммутабельностью при явном объявлении типа.
Кроме того, Java позволяет использовать var только для локальных переменных, но не для полей. Для полей иммутабельность более значима. Неизменяемые локальные переменные используются сравнительно редко.
Использование ключевых слов var/val для управления иммутабельностью — это то, что действительно стоит позаимствовать из Scala в Java. Однако в Java это было бы гораздо менее полезно, чем в Scala.
Вопрос 4. Не будут ли плохие разработчики злоупотреблять var, чтобы писать ужасный код?
Да, плохие разработчики будут писать ужасный код, что бы мы ни делали. Отказ от var не помешает им это сделать. Но при правильном применении выведение типов позволит писать более качественный код.
Один из моментов, благодаря которому var может побудить разработчиков писать более качественный код, заключается в том, что var снижает накладные расходы на объявление новой переменной. Разработчики часто избегают объявления новой переменной, если это требует больших затрат, и создают сложные конструкции, ухудшающие читаемость, только из-за того, чтобы избежать объявления дополнительных переменных. С var накладные расходы на извлечение части кода в именованную переменную уменьшаются, поэтому разработчики с большей вероятностью будут это делать, что приведет к более чистому коду.
Часто программисты начинают очень активно использовать новые возможности языка, возможно, злоупотребляя ими, и требуется некоторое время, чтобы сообщество выработало рекомендации по разумному использованию.
Начиная с выведения типа локальной переменной (Local Variable Type Inference, LVTI), мы публикуем материалы о назначении и рекомендации по использованию (например, данный FAQ и LVTI Style Guidelines) почти одновременно с появлением этой функциональности. Мы надеемся, что это ускорит понимание в сообществе, когда разумно использовать var , и поможет избежать злоупотребления.
Вопрос 5. Где можно использовать var?
var может использоваться при объявлении локальных переменных, включая индексные переменные цикла for и ресурсные переменные оператора try-with-resources .
var нельзя использовать для полей, параметров методов и возвращаемых типов методов. Причина заключается в том, что типы в этих местах явно присутствуют в class-файлах и в спецификациях Javadoc. При выведении типа изменение инициализатора может легко привести к изменению предполагаемого типа переменной. Для локальных переменных это не проблема, так как область видимости локальных переменных ограничена, и их типы напрямую не записываются в class-файлы. Однако для полей, параметров методов и типов, возвращаемых методом, выведение типа может легко вызвать проблему.
Например, возвращаемый тип метода был выведен из выражения в операторе return . Изменение реализации метода может привести к изменению типа выражения в return . Это, в свою очередь, может изменить тип возвращаемого значения. Что может привести к бинарной несовместимости или несовместимости в исходном коде. Такие несовместимые изменения не должны возникать из-за безобидных на вид изменений в реализации.
Предположим, что также будет выводиться тип поля. Тогда изменение инициализатора поля может привести к изменению типа поля, что может неожиданно нарушить рефлексивный код.
Выведение типа допустимо в реализации, но не в API. API-контракты должны быть объявлены явно.
Как насчет private-полей и методов, которые не являются частью API? Теоретически мы могли бы реализовать поддержку var для private-полей и возвращаемых типов для private-методов, не опасаясь, что это вызовет несовместимость из-за раздельной компиляции и динамической линковки. Но для простоты мы решили ограничить область выведения типов. Если расширить границы и включить отдельные виды полей и типы, возвращаемые некоторыми методами, то это сделает все значительно более сложным и трудным для понимания, и лишь незначительно более полезным.
Вопрос 6. Почему для var всегда нужен инициализатор в правой части?
Тип переменной вычисляется на основе инициализатора. Это означает, что var можно использовать только при наличии инициализатора. Можно было бы сделать выведение типа из присвоений переменной, но это значительно усложнило бы реализацию и потенциально могло привести к вводящим в заблуждение или трудно диагностируемым ошибкам. Для простоты мы определили var так, чтобы для выведения типа использовалась только локальная информация.
Допустим, мы разрешили выведение типа на основе присваивания в нескольких местах, отдельно от объявления переменной. Тогда рассмотрим следующий пример:
Если тип был выбран на основе, например, первого присваивания, то это может привести к ошибке в другом операторе, весьма удаленном от местоположения настоящей ошибки. (Иногда это называют проблемой «дальнодействия».)
В качестве альтернативы можно выбрать тип, совместимый со всеми присваиваниями. И в этом случае можно ожидать, что выведенный тип будет Object , как общий суперкласс String и Integer . К сожалению, ситуация сложнее. Поскольку и String , и Integer являются Serializable и Comparable , общий супертип будет пересечением типов, что-то вроде
Обратите внимание, что невозможно явно объявить переменную этого типа. Также это приводит к упаковыванию (boxing), когда order присваивается 2, что может быть неожиданным и нежелательным.
Чтобы избежать подобных проблем, проще потребовать вывод типа с использованием явного инициализатора.
Вопрос 7. Почему нельзя использовать var с null?
Посмотрите на такое объявление (оно некорректно):
Литерал null обозначает значение специального типа null (JLS 4.1), который является подтипом всех ссылочных типов в Java. Единственным значением типа null является сам null , поэтому единственное значение, которое может быть присвоено переменной типа null — это null . Это не очень полезно.
Можно ввести специальное правило, чтобы объявление var , инициализированное значением null , имело тип Object . Но возникает вопрос о намерениях программиста. Предположим, что переменная инициализируется значением null , чтобы позже ей присвоить какое-либо другое значение. Но в этом случае маловероятно, что определение типа переменной как Object будет правильным.
Вместо того чтобы создавать какие-то специальные правила для обработки этого случая, мы его запретили. Если вам нужна переменная типа Object , объявите ее явно.
Вопрос 8. Можно ли использовать var с diamond-оператором справа?
Да, это работает, но, скорее всего, не так, как вы ожидаете. Пример:
Тип списка будет ArrayList<Object> . В общем, лучше указывать явный тип слева с diamond-оператором справа или использовать var слева с явным типом справа. См. особенности использования var с diamond-оператором и дженериками в LVTI Style Guidelines (Руководство по стилю LVTI).
Приглашаем всех желающих на открытое занятие «Реляционные базы данных для начинающих Java-разработчиков». Поговорим о месте реляционных баз данных в архитектуре информационных систем. Рассмотрим основные компоненты и возможности РСУБД на примере PostgreSQL. Сделаем обзор основных технологий по работе с реляционными БД в Java (JDBC, JPA/Hibernate, Spring Data и др.) Регистрация по ссылке.