Ключевое слово var (Java 10+)

Начиная с Java 10 (JEP 286), в язык введён механизм локального вывода типов (Local Variable Type Inference). Ключевое слово var позволяет объявить локальную переменную без явного указания её типа — компилятор сам выведет тип по правой части выражения.

Важно понимать: var — это не динамическая типизация. Java остаётся строго типизированным языком. Тип переменной фиксируется на этапе компиляции и не может измениться в дальнейшем.

Минимальная версия: Java 10.

Синтаксис

var имяПеременной = выражение;

Правая часть обязана быть выражением, по которому компилятор может определить тип. Поэтому объявление без инициализации запрещено.

Зачем нужно

  • Сокращает шум в коде, особенно с длинными generic-типами.

  • Делает код ближе по стилю к Kotlin/Scala/Swift, не нарушая строгой типизации.

  • Уменьшает повторение типа на обеих сторонах присваивания (DRY).

Примечание

var работает только для локальных переменных внутри методов, циклов и блоков. Для полей класса, параметров методов и возвращаемых значений по-прежнему нужен явный тип.

Пример 1. Базовое использование

public class VarBasic {
    public static void main(String[] args) {
        var number = 42;             // int
        var pi = 3.14;               // double
        var name = "AlashEd";        // String
        var flag = true;             // boolean

        System.out.println(number + " " + pi + " " + name + " " + flag);
    }
}

Output:

42 3.14 AlashEd true

Пример 2. Generic-коллекции

import java.util.HashMap;
import java.util.Map;

public class VarCollections {
    public static void main(String[] args) {
        // Без var:
        Map<String, Integer> sensors1 = new HashMap<String, Integer>();
        // С var — короче:
        var sensors = new HashMap<String, Integer>();

        sensors.put("trig", 3);
        sensors.put("echo", 7);
        sensors.put("servo", 9);

        System.out.println("Размер: " + sensors.size());
        System.out.println("trig pin: " + sensors.get("trig"));
    }
}

Output:

Размер: 3
trig pin: 3

Пример 3. Цикл for

import java.util.List;

public class VarLoop {
    public static void main(String[] args) {
        var pins = List.of(2, 4, 5, 6, 8, 12);

        for (var pin : pins) {
            System.out.println("Pin D" + pin);
        }
    }
}

Output:

Pin D2
Pin D4
Pin D5
Pin D6
Pin D8
Pin D12

Пример 4. try-with-resources

import java.io.BufferedReader;
import java.io.StringReader;
import java.io.IOException;

public class VarTryWith {
    public static void main(String[] args) throws IOException {
        var text = "L298N\nRCWL-9610A\nSG92R";
        try (var reader = new BufferedReader(new StringReader(text))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("Компонент: " + line);
            }
        }
    }
}

Output:

Компонент: L298N
Компонент: RCWL-9610A
Компонент: SG92R

Пример 5. Сложный generic-тип

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class VarComplex {
    public static void main(String[] args) {
        // Без var громоздко:
        // Map<String, List<Integer>> kits = new HashMap<String, List<Integer>>();
        var kits = new HashMap<String, List<Integer>>();

        kits.put("RobotPhobo", new ArrayList<>(List.of(2, 4, 5, 6, 8, 12)));
        kits.put("Sensors", new ArrayList<>(List.of(3, 7, 9)));

        for (var entry : kits.entrySet()) {
            System.out.println(entry.getKey() + " -> " + entry.getValue());
        }
    }
}

Output:

RobotPhobo -> [2, 4, 5, 6, 8, 12]
Sensors -> [3, 7, 9]

Пример 6. Что НЕ компилируется

public class VarErrors {
    // var field = 10;            // ОШИБКА: var нельзя для полей класса
    // public void m(var x) { }   // ОШИБКА: var нельзя в параметрах

    public static void main(String[] args) {
        // var x;                 // ОШИБКА: нужна инициализация
        // var y = null;          // ОШИБКА: тип null не определим
        // var arr = {1, 2, 3};   // ОШИБКА: литерал массива требует типа

        // Правильные варианты:
        var x = 0;
        Object y = null;
        var arr = new int[] {1, 2, 3};

        System.out.println(x + " " + y + " длина=" + arr.length);
    }
}

Output:

0 null длина=3

Подводные камни

Предупреждение

  • var нельзя использовать для полей класса, параметров и возвращаемых значений.

  • Нельзя объявить без инициализации: var x; — ошибка.

  • Нельзя var x = null — компилятор не знает тип.

  • Нельзя var arr = {1, 2, 3} — нужен new int[] {...}.

  • Не злоупотребляйте: var result = doSomething(); ухудшает читаемость, если имя метода не отражает тип.

  • При работе с var и diamond (<>) можно получить Object там, где вы ожидаете generic: var list = new ArrayList<>(); даст ArrayList<Object>.

Совет

Используйте var там, где тип очевиден из правой части (например, конструктор) или слишком громоздок. Не используйте, когда тип несёт смысловую нагрузку, отсутствующую в имени.

См. также

Примечание

Материал основан на официальной документации Oracle Java SE (docs.oracle.com/en/java/javase) и спецификации JEP 286 (openjdk.org/jeps/286), распространяемой под лицензией Oracle Free Documentation License. Тексты и примеры написаны заново для AlashEd Wiki.