Почему мы не можем заполнить нестатическую коллекцию вне метода?

#java #collections

Вопрос:

Я случайно написал этот код и обнаружил ошибки:

 class Main {
    LinkedList<Integer> list = new LinkedList<>();
    list.add(10);
    list.add(5);

    public static void main(String[] args) {
        Main myObj = new Main();
        System.out.prinln(myObj.list);
    }
}
 

Если я объявляю LinkedList статическим и заполняю его статическим блоком, ошибки нет, или если я создаю метод, а затем заполняю список внутри метода, то также ошибки нет.

Я новичок и не могу понять причину, по которой он не заполняется, когда я пытаюсь, как в приведенном выше коде. Пожалуйста, объясните это как для 1-го стандартного студента. Спасибо!

Комментарии:

1. Вы хотите, чтобы он был заполнен при Main создании объекта ( new Main() )? если это так, добавьте эти строки в конструктор .

Ответ №1:

… причина, по которой он не заполняется, когда я пытаюсь, как в приведенном выше коде.

Потому что язык Java был разработан таким образом. list.add(10) это вызов метода, и существуют ограничения на то, где разрешены вызовы методов. Было бы вполне возможно разработать язык, который позволял бы вызовы методов (и другие операторы) чередоваться с объявлениями в классе. Однако я не видел этого ни на одном языке. В конце концов, это также может привести к путанице.

Позвольте два предложения:

  1. Подумайте дважды, прежде чем использовать a LinkedList .
  2. Заполните свой список в декларации.

За свои 20 с лишним лет работы Java-программистом я однажды использовал a LinkedList и, оглядываясь назад, пожалел об этом. У этого класса так мало хороших применений. ArrayList почти всегда будет более эффективным с точки зрения времени и пространства.

Начиная с Java 9, вы можете объявлять и заполнять список таким образом, если его не нужно изменять:

 List<Integer> list = List.of(10, 5);
 

Если вам понадобится возможность изменить список позже:

 List<Integer> list = new ArrayList<Integer>(List.of(10, 5));
 

Кстати , то же самое работает и для LinkedList . В Java 8 и более ранних версиях вы можете использовать Arrays.asList() , например:

 List<Integer> list = new ArrayList<Integer>(Arrays.asList(10, 5));
 

Ответ №2:

Если мы разберем приведенный выше код, он будет состоять из class именованного «Основного», содержащего:

  • variable Именованный «список» типа LinkedList
  • Заявление list.add(10);
  • Еще одно заявление list.add(5);
  • Метод с именем «main», содержащий еще 2 оператора.

A class в java-это языковая конструкция, которой разрешено иметь определенные типы членов.

Спецификации java сообщают нам, какие члены класса могут иметь:

В теле класса объявляются члены (поля, методы, классы и интерфейсы), инициализаторы экземпляров и статические инициализаторы, а также конструкторы

https://docs.oracle.com/javase/specs/jls/se16/html/jls-8.html#jls-8.2

Проблема с приведенным выше кодом заключается в том, что операторы не могут быть членами класса. Компилятор отклонит их.

Java, однако, предоставляет нам инструмент для заполнения коллекции вне метода. Это статические инициализаторы

Редактировать: Спасибо @Ole V. V. и @fps за то, что поправили меня здесь

Это инициализатор экземпляра

Инициализатор экземпляра, объявленный в классе, выполняется при создании экземпляра класса

https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.6

Применительно к приведенному выше коду мы можем написать:

 import java.util.LinkedList;

class Main {
    LinkedList<Integer> list = new LinkedList<>();
    { // This bracket starts the initializer 
        list.add(10);
        list.add(5);
    } // This bracket closes the initializer
    
    public static void main(String[] args) {
        Main myObj = new Main();
        System.out.println(myObj.list);
    }
}
 

Надеюсь, это немного поможет 🙂

Комментарии:

1. Это инициализатор экземпляра, как говорит @OleV.V.. Статические инициализаторы используются для инициализации переменных класса, а переменная класса является статической переменной, переменная класса-это просто еще один способ вызова статической переменной. Инициализаторы экземпляра, с другой стороны, полезны для инициализации полей экземпляра, таких как связанный список вопроса (т. е. нестатические члены).

2. Помимо этой небольшой путаницы в отношении статических и нестатических инициализаторов, ваш ответ превосходен

3. О, я все это время ошибался 🙂 Спасибо обоим за разъяснение этого!