Что такое var в java
Перейти к содержимому

Что такое var в java

  • автор:

Что такое 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. Local Variable Type Inference: Style Guidelines 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.

How to use var keyword to declare local variables in Java? Example Tutorial

We’ve moved to freeCodeCamp.org/news

Hello everyone! In this article, I’ll discuss new features of Java 10. Specifically, I am going to talk about probably the most popular and most useful: the introduction of the var keyword in Java. Well, it’s not really a keyword — but I’ll tell you about it later.

At long last…

Finally, Java has gotten the var keyword to declare local variables. This allows you to declare a variable without its type. For example, instead of doing this:

String str = “Java”

you can now just say this:

This may not sound like much to gain when you’re declaring a String or an int variable but think about complex types with generics, for example. This will surely save a lot of typing, and will also improve the readability of the code.

A little background

Java developers have long been complaining about boilerplate code and the ceremonies involved while writing code. Many things which take just 5 minutes in languages like Python, Groovy, or JavaScript can take more than 30 minutes in Java due to its verbosity.

If you have coded in Scala, Kotlin, Go, C# or any other JVM language, then you know that they all have some kind of local variable type inference already built into the language.

For example, JavaScript has let and var, Scala and Kotlin have var and val, C++ has the auto, C# has var, and Go supports this by declaration with the := operator.

Until Java 10, Java was the only language which didn’t have local variable type inference or support for the var keyword.

Though type inference was improved a lot in Java 8 with the introduction of the lambda expression, method references, and Streams, local variables still needed to be declared with a proper type. But that’s now gone! Java 10 has a feature, JEP 286: Local-Variable Type Inference, which will allow declaring local variables without type information and by just using the var keyword.

Let’s take a closer look.

Java 10 var keyword examples

Here are some examples of Java 10's var keyword:

As I said, at this point you may not fully appreciate what var is doing for you. But look at the next example:

Here, the list will be inferred into List<? extends Serializable & Comparable<..>> which is an intersection type, but you won’t have to type the full type information. var makes the code much easier to write and read in this case.

In the next section, we’ll see some more examples that’ll help you learn how to write concise code using var in Java 10.

Writing concise code using the var keyword in Java

The use of the var reserve word also makes your code concise by reducing duplication — for example, the name of the Class which comes on both the right and left-hand side of assignments as shown in the following example:

Here ByteArrayOutputStream repeats twice, and we can eliminate that by using the var feature of Java 10 as shown below:

We can do similar things while using try-with-resource statements in Java, for example, this

can be written as follows:

These are just a few examples. There are a lot of places where you can use var to make your code more concise and readable, many of which you can see on Sander’s Pluralsight course What’s New in Java 10.

It’s a paid course but you can check out this 10-day free trial.

For those programmers who have used Groovy or Scala, the introduction of var makes it seem like Java is going the Scala way…but only time will tell.

For now, we can just be happy that var makes it easier to declare a complex local variable in Java 10.

And do note: the local variable type inference of the Java 10 var keyword can only be used to declare local variables (for example, any variable inside the method body or code block).

Can you use var to declare member variables in Java?

You cannot use var to declare member variables inside the class, method formal parameters or return type of methods.

For example, this example of var is OK:

But, the following example is NOT OK:

So, even though this new Java 10 feature is eye-catching and looks good, it still has a long way to go. Still, you can start using it to further simplify your code. Less boilerplate code always means better and more readable code.

Important points about this new var keyword

Now that you know that you can declare local variables without declaring the type in Java 10, it’s time to learn a few important things about this feature before you start using it in your production code:

1. This feature is built under JEP 286: Local-Variable Type Inference and was authored by none other than Brian Goetz. He’s the author of Java Concurrency in Practice, one of the most popular books for Java developers.

2. The var keyword allows local variable type inference, which means the type for the local variable will be inferred by the compiler. Now you don’t need to declare it.

3. The local variable type inference or Java 10 var keyword can only be used to declare local variables, for example inside methods, on initializers code block, indexes in the enhanced for loop, lambda expressions, and local variables declared in a traditional for loop.

You cannot use it for declaring formal variables and return types of methods, for declaring member variables or fields, on constructor formal variables, and any other kind of variable declaration.

4. Despite the introduction of var, Java is still a statically typed language and there should be enough information to infer the type of the local variable. If not, the compiler will throw an error.

5. The var keyword is similar to the auto keyword of C++, var of C#, JavaScript, Scala, Kotlin, def of Groovy and Python (to some extent), and the : = operator of the Go programming language.

6. One important thing to know is that, even though var looks like a keyword, it’s not really a keyword. Instead, it is a reserved type name. This means that code that uses var as a variable, method, or package name will not be affected.

7. Another thing to note is that code that uses var as a class or interface name will be affected by this Java 10 change. But as JEP says, these names are rare in practice, since they violate usual naming conventions.

8. The immutable equivalent of local variables or final variables val and let is not yet supported in Java 10.

Wrapping up

That’s all about the var in Java 10! It’s an interesting Java 10 feature, which allows you to declare local variables without declaring their type. This will also help Java developers pick up other languages quickly, like Python, Scala, or Kotlin, because they heavily use var to declare mutable variables and val to declare immutable local variables.

Even though JEP 286: Local-Variable Type Inference only supports var and not val, it is still useful and feels more like coding Scala in Java.

Further Learning

Thanks for reading this article. If you like this new Java 10 feature, then please share it with your friends and colleagues.

If you have any questions or feedback, please drop a note and stay tuned for more Java 10 tutorials and articles here.

Что такое var в java

The var reserved type name (not a Java keyword) was introduced in Java 10. Type inference is used in var keyword in which it detects automatically the datatype of a variable based on the surrounding context. The below examples explain where var is used and also where you can’t use it.

1. We can declare any datatype with the var keyword.

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 и др.) Регистрация по ссылке.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *