Как объединяются "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

Заключение:

  1. Не используйте необработанные типы независимо от наличия или отсутствия var.
  2. Убедитесь, что аргументы метода или конструктора предоставляют достаточную информацию о типе, чтобы предполагаемый тип соответствовал вашему намерению. В противном случае избегайте использования обоих var с diamond 1.

1 - Руководство по стилю для локального ввода типа переменной: G6.Будьте осторожны при использовании var с алмазными или родовыми методами.