/ / Instantiating Generics: new ArrayList <?> () Vs new ArrayList <List <? >> () [duplicate] - java, generics

Tworzenie instancji Generics: new ArrayList <?> () Vs nowa ArrayList <lista <? >> () [duplicate] - java, generics

Dlaczego jest to dozwolone:

List<List<?>> list = new ArrayList<List<?>>()

ale nie to?

List<?> list = new ArrayList<?>(); //Compile error: "Cannot instantiate the type ArrayList<?>"

Odpowiedzi:

3 dla odpowiedzi № 1

Kiedy tworzysz ArrayList, musisz zdefiniować typ obiektów, które będzie ona zawierać:

  • w pierwszym przykładzie utworzysz ArrayList, który będzie zawierał listy nieznanych typów ogólnych, ale wszystkie będą listami.
  • w drugim przykładzie próbujesz utworzyć ArrayList nieznanego typu, co jest niedozwolone.

1 dla odpowiedzi nr 2

Nie można utworzyć instancji obiektu o nieznanej nazwie ogólnej, dlatego druga linia nie działa.

List<?> list = new ArrayList<String>();

Działa jednak podczas korzystania z „listy”, kod nie wiedziałby, że była to lista String, co czyni ją raczej bezużyteczną.

Pierwsze wywołanie działa, ponieważ zostało określoneże chcesz utworzyć tablicową listę innych list, jakie to listy zostaną określone, kiedy faktycznie utworzysz listy potomne. Tutaj tworzysz tylko listę nadrzędną, która jest faktycznie listą list.


0 dla odpowiedzi № 3

Pomyśl o definicji typu ogólnego jako o obu

  1. Definicja pewnego rodzaju konstruktora umożliwiająca tworzenie nowej nietypowej „instancji typu” typu ogólnego.
  2. Definicja typu.

Teraz przetłumaczmy tę logikę na zmienne nieogólne:

CharSequence val = new String("foo");

jest całkowicie legalny. Zmienna val reprezentuje typ (2) i oczywiście nigdy nie będzie bezpośrednich wystąpień interfejsu CharSequence. Jednak nie mogłeś skonstruować (1) tego typu, ale można przypisać do niego przypisywalny podtyp, taki jak String. Nie można zastąpić tworzenia ciągu przez podanie czegoś takiego new [? extends CharSequence], musisz jawnie nazwać typ, który ma zostać zbudowany.

Wróćmy teraz do ogólnych, gdzie rzeczy są podobne. Kiedy wywołujesz konstruktor typu ogólnego.

new ArrayList<List<?>>()

jesteś w pewien sposób konstruowanie (2) nowa „instancja typu” typu ogólnego, w której należy jawnie przypisać wartość zmiennej typu T ogólnej definicji w ArrayList<T>. ? sam w sobie nie opisuje typu Java i dlatego nie może być stosowany jako wartość przypisania. Jednak inne niż T = ?, definicja T = List<?> jest możliwe, ponieważ symbol wieloznaczny może być częścią prawidłowej definicji typu Java.

Podczas używania symbolu wieloznacznego w definicja typu (1) jak w

List<?> list

nie jesteś konstruowanie nowy rodzaj ogólny, opisujesz jedynie granice jednego. Dlatego przy tej okazji można użyć symbolu wieloznacznego.