Какая разница между List <Object> и List <?> - программирование
Подтвердить что ты не робот

Какая разница между List <Object> и List <?>

Прежде, чем все вы сожжете меня живым, я должен сказать, что у меня много раз задавался этот вопрос, и я все еще не понимаю разницы между List <Object> и List <? >

Все прочитанные мной книги говорят, что в Java каждый класс является неявным подклассом Object.

Однако я увидел здесь следующий код:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

Этот код неправильный (намеренно для образовательных целей), и, по мнению автора, причина такова:

[...] печатает только список экземпляров объекта; он не может печатать List <Integer> , List <String> , List <Double> и т.д., поскольку они не являются подтипами List <Object>

Решение:

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

Как вы можете видеть, единственная разница - это первая строка:

public static void printList(List<Object> list) {
public static void printList(List<?> list) {

Вот почему мой вопрос: какая разница между List <Object> и List <? >

В конце концов, это суперкласс класса или нет?

Если кто-то может помочь мне с простым объяснением (я новичок в Java), я буду признателен.

Спасибо заранее.

4b9b3361

Ответ 1

Объяснение:

? является "подстановочным знаком". Вы можете использовать его по-разному:

неограниченный шаблон:

? 

подстановочный знак с верхней границей:

? extends Object (or another class)

с нижней границей

? super Object (or another class)

Примеры:

List <?> list;

вы можете назначить list любому списку с любым параметром типа.

List<? extends Number> list;

вы можете назначить список любого списка с типом параметра Number (или Integer, Float, ecc)

List<? super Integer> list;

вы можете назначить список любого списка с параметром типа Integer или типом в герархии типа Integer (Number, Comparable, Serializable, Object...)

Резюме:

Итак, декларация

List<Object> list;

похож на

List<? super Object> list;

потому что вы можете назначить "список" только списку объектов; то вы можете использовать список следующим образом:

    list = new ArrayList<Object>();
    list.add(new String(""));
    list.add(new Integer(3));

Ответ 2

Одним из основных отличий является то, как вы можете изменять списки. Хорошо работает следующее:

List<Object> l1;
l1.add(new Object()); // OK

в то время как второй случай создает ошибку компиляции.

List<?> l2;
l2.add(new Object()); // Compile error

Причины этого, я думаю, несколько раз обсуждались на сайте. Короче говоря, <?> означает a (как в одном) конкретный, но неизвестный тип. Поскольку этот тип не известен во время компиляции, вам не разрешается изменять список.

Ответ 3

То, что String является подтипом Object, не означает, что List<String> является подтипом List<Object>. Если это так, следующий код будет компилироваться:

List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
objects.add((Integer) 1);
strings.get(0).charAt(0); // but the Integer 1 does not have a charAt method ...

Следовательно, List<String> не является подтипом List<Object>.

Оба List<String> и List<Object> являются подтипами List<?>. Но поскольку List<?> является более общим типом, вы не можете знать, какой тип принимает метод add:

List<String> strings = new ArrayList<String>();
List<?> objects = strings;
objects.add((Integer) 1); // does not compile

Ответ 4

В основном вы можете использовать обе версии аналогичным образом. Однако есть одна большая разница. Пусть объявить следующее:

List<Object> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<String>();

Теперь попробуйте код ниже:

list1.add("");// this works fine
list2.add("");// this one issues a compile error

Кто-то может спросить, почему это. Это связано с тем, что в List<Object> код сообщает вам, что у вас есть Object или подтипы, но в List<?> у вас может быть одно и то же, но вы точно не знаете. Кто-то может добавить String или Double, а затем попытаться прочитать и приложить к Integer. Но опять же это невозможно.

Могут быть и другие отличия, о которых я не помню сейчас.

Ответ 5

Этот код неправильный (намеренно для образовательных целей), и, по мнению автора, причина такова:

[...] печатает только список экземпляров объекта; он не может печатать Список, список, список и т.д., Потому что они не подтипы List

Это связано с тем, что параметризованные типы инвариантны, например, для классов X и Y, List<X> не является ни подтипом, ни супертипом List<Y>.

Разница заключается в том, что неограниченный тип подстановок ? означает, что тип неизвестен, и вы не можете ничего с этим поделать. A List<?> безопасен по типу, вы не можете поместить в него какой-либо элемент, отличный от null, и вы не можете предположить ничего о типе содержащегося в нем объекта.

List<Object>, очевидно, означает, что List может содержать объекты любого типа.

Ответ 6

Объект - это суперкласс String, но List <Object> не является суперклассом List <String> . Если бы это было так, это было бы проблемой:

List<String> strings = ...
addObject(strings);
...
void addObjects(List<Object> objects) {
    objects.add(new Object());
}

Теперь строки содержат элемент, который не является строкой.

Ответ 7

 public static void main(String args[]){

   List<? super Object> list=new ArrayList<>();
   list.add("A");//works

   List<Object> list1=new ArrayList<>();
   list1.add("B");//works

   List<?> list2=new ArrayList<>();
   list2.add("11");//compile time error;

   List<? extends Object> list4=new ArrayList<>();
   list4.add("123");//compile Time error
}

Список <? расширение Object > и List <? > не позволяет добавить что-либо следовать этому, чтобы узнать причину: введите описание ссылки здесь Но, с другой стороны, List <? super Object > позволяет добавлять значения в список, потому что проблема в предоставленной ссылке не существует.