Как объединяются "var" и raw типы?
Я наткнулся на ответ, который предлагает использовать
var list = new ArrayList();
Я был удивлен, обнаружив здесь необработанный тип, и мне просто интересно: использует ли var
<>
"автоматически?
(в то же время ответ был изменен на использование <String>
, но мне все еще интересно, но "принципы" здесь)
Я видел другие вопросы, такие как это, но все они используют оператора бриллианта:
var list = new ArrayList<>();
Теперь я просто задаюсь вопросом: изменяет ли var
как мы должны (не) использовать необработанные типы? Или это предложение отказаться от <>
просто плохой практики?
Ответы
Ответ 1
Я наткнулся на ответ, который предлагает использовать...
Я бы проигнорировал этот ответ, потому что, как вы указываете, он использует необработанные типы, и он отображает list
как специфический ArrayList
. (Обновление: ответчик отредактировал свой ответ, чтобы добавить тип элемента.) Вместо этого:
List<AppropriateElementType> list = new ArrayList<>();
В соответствии со вторым ответом, который вы связали, var
заставит компилятор вывести тип элемента из правой части, если вы включите <>
, выбрав наиболее подходящий тип, который он может. В var list = new ArrayList<>();
это будет ArrayList<Object>
, хотя, поскольку он не имеет ничего более конкретного, он может выбрать.
Но, это:
var list = new ArrayList();
... без <>
, использует необработанный тип (ArrayList
), а не параметризованный тип с Object
в качестве параметра (ArrayList<Object>
), который отличается.
Если использование list
достаточно содержалось (несколько строк в методе), то его типизация ArrayList<X>
а не List<X>
может быть приемлемой (зависит от вашего стиля кодирования), и в этом случае:
var list = new ArrayList<AppropriateElementType>();
Но обычно я предпочитаю кодировать интерфейс, а не конкретный класс, даже с местными жителями. Тем не менее, с местными жителями это менее важно, чем с членами экземпляра, и var
удобен.
Ответ 2
Легально использовать как var
и diamond
, но выводимый тип изменится:
var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>
Для его вывода diamond
может использовать целевой тип (как правило, левую часть объявления) или типы аргументов конструктора. Если ни один из них не присутствует, он возвращается к самому широкому применимому типу, который часто является Object
1.
С помощью как diamond
и общих методов дополнительная информация типа может быть предоставлена фактическими аргументами конструктору или методу, позволяя предполагаемому типу быть выведенным 1:
var list = List.of(BigInteger.ZERO); // OK: infers as List<BigInteger>
var list = new ArrayList<String>( ); // OK: infers as ArrayList<String>
Ввиду вышеизложенного, я не рекомендую делать следующее (потому что вы получите необработанный тип ArrayList
):
var list = new ArrayList(); // DANGEROUS: infers as ArrayList
Заключение:
- Не используйте необработанные типы независимо от наличия или отсутствия
var
. - Убедитесь, что аргументы метода или конструктора предоставляют достаточную информацию о типе, чтобы предполагаемый тип соответствовал вашему намерению. В противном случае избегайте использования обоих
var
с diamond
1.
1 - Руководство по стилю для локального ввода типа переменной: G6.Будьте осторожны при использовании var с алмазными или родовыми методами.