1. Обзор
Одним из наиболее заметных улучшений в JDK 10 является определение типа локальных переменных с помощью инициализаторов.
В этом руководстве подробно рассказывается об этой функции с примерами.
2. Введение
До Java 9 нам приходилось явно указывать тип локальной переменной и обеспечивать ее совместимость с инициализатором, используемым для ее инициализации:
String message = "Good bye, Java 9";
В Java 10 мы могли бы объявить локальную переменную следующим образом:
@Test
public void whenVarInitWithString_thenGetStringTypeVar() {
var message = "Hello, Java 10";
assertTrue(message instanceof String);
}
Мы не предоставляем тип данных сообщения
. Вместо этого мы помечаем сообщение
как переменную
, и компилятор делает вывод о типе сообщения
из типа инициализатора, представленного в правой части.
В приведенном выше примере тип сообщения
будет String
.
Обратите внимание, что эта функция доступна только для локальных переменных с инициализатором. Его нельзя использовать для переменных-членов, параметров метода, возвращаемых типов и т. д. — требуется инициализатор, без которого компилятор не сможет определить тип.
Это усовершенствование помогает сократить шаблонный код; Например:
Map<Integer, String> map = new HashMap<>();
Теперь это можно переписать как:
var idToNameMap = new HashMap<Integer, String>();
Это также помогает сосредоточиться на имени переменной, а не на ее типе.
Следует также отметить, что var
не является ключевым словом — это обеспечивает обратную совместимость для программ, использующих var
, скажем, в качестве имени функции или переменной. var
— зарезервированное имя типа, как и int
.
Наконец, обратите внимание, что при использовании var
нет накладных расходов во время выполнения и это не делает Java языком с динамической типизацией. `` Тип переменной выводится во время компиляции и не может быть изменен позже.
3. Незаконное использование var
Как упоминалось ранее, var
не будет работать без инициализатора:
var n; // error: cannot use 'var' on variable without initializer
Это также не сработает, если оно инициализировано с помощью null
:
var emptyList = null; // error: variable initializer is 'null'
Это не будет работать для нелокальных переменных:
public var = "hello"; // error: 'var' is not allowed here
Для лямбда-выражения требуется явный целевой тип, поэтому var
нельзя использовать:
var p = (String s) -> s.length() > 10; // error: lambda expression needs an explicit target-type
То же самое и с инициализатором массива:
var arr = { 1, 2, 3 }; // error: array initializer needs an explicit target-type
4. Рекомендации по использованию var
Бывают ситуации, когда var
можно использовать на законных основаниях, но это может быть не очень хорошей идеей.
Например, в ситуациях, когда код может стать менее читаемым:
var result = obj.prcoess();
Здесь, несмотря на легальное использование var
, становится трудно понять тип, возвращаемый process()
, что делает код менее читаемым.
На java.net есть специальная статья «Рекомендации по стилю для определения типа локальной переменной в Java» , в которой рассказывается о том, как мы должны использовать суждение при использовании этой функции.
Другая ситуация, когда лучше избегать var
, — это потоки с длинным конвейером:
var x = emp.getProjects.stream()
.findFirst()
.map(String::length)
.orElse(0);
Использование var
также может дать неожиданный результат.
Например, если мы используем его с оператором алмаза, представленным в Java 7:
var empList = new ArrayList<>();
Тип empList
будет ArrayList<Object>
а не List<Object>
. Если мы хотим, чтобы это был ArrayList<Employee>
, мы должны быть явными:
var empList = new ArrayList<Employee>();
Использование var
с неопределяемыми типами может привести к непредвиденной ошибке.
Например, если мы используем var
с экземпляром анонимного класса:
@Test
public void whenVarInitWithAnonymous_thenGetAnonymousType() {
var obj = new Object() {};
assertFalse(obj.getClass().equals(Object.class));
}
Теперь, если мы попытаемся присвоить obj другой
объект
, мы получим ошибку компиляции: ``
obj = new Object(); // error: Object cannot be converted to <anonymous Object>
Это связано с тем, что предполагаемый тип obj
не является Object
.
5. Вывод
В этой статье мы увидели новую функцию вывода типа локальной переменной Java 10 с примерами.
Как обычно, фрагменты кода можно найти на GitHub .