Подтвердить что ты не робот

Разница между несвязанным подстановочным знаком и необработанным типом

Я читал о дженериках, и я не понимал необходимости для несвязанных подстановочных знаков и того, как он отличается от необработанного типа. Я прочитал этот вопрос, но все еще не понял его. На странице Java tutorial для несвязанного подстановочного знака я получил ниже двух пунктов, и я не понял первого пункта:

  • Если вы пишете метод, который может быть реализован с использованием функциональных возможностей, предоставляемых в классе Object.
  • Когда код использует методы в общем классе, которые не зависят от параметра типа. Например, List.size() или List.clear(). На самом деле, Class<?> так часто используется, потому что большинство методов из Class<T> не зависят от T.

Может кто-то объяснит разницу между несвязанным подстановочным знаком и необработанным типом на языке неспециалиста.

Как List<?> отличается от List<Object>?

4b9b3361

Ответ 1

Как List<?> отличается от List<Object>

Основное отличие состоит в том, что первая строка компилируется, а вторая не делает:

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

Однако, поскольку вы не знаете, что такое общий тип List<?>, вы не можете использовать его параметризованные методы:

List<?> list = new ArrayList<String> ();
list.add("aString"); //does not compile - we don't know it is a List<String>
list.clear(); //this is fine, does not depend on the generic parameter type

Что касается разницы с необработанными типами (без дженериков), код ниже компилируется и работает нормально:

List list = new ArrayList<String> ();
list.add("aString");
list.add(10);

Ответ 2

Как List<?> отличается от List<Object>?

    List<Object> l1 = new ArrayList();
    List<?> l2 = new ArrayList();
    l1.add("Object");
    //l2.add("Object");   incorrect
    l2.add(null);

Вы можете добавить только нулевое значение в List<?>

Ответ 3

Лично я нашел эту дополнительную ссылку из учебника Java по шаблонам.

Одно из основных различий, которое я вижу между List<?> и List, состоит в том, что первое может быть полезно только для чтения из него элементов (если вы действительно не хотите добавить null), последний позволяет (не отмечен) добавление к нему произвольно типизированных объектов с возможными неожиданными побочными эффектами.

Ответ 4

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

void someMethod(List<?> list) {
  list.clear();  // I will never add anything to the list in here
}

Вы никогда не будете добавлять что-либо или иным образом изменять список в отношении типа, который он содержит, поскольку вы не можете добавить что-либо в список, кроме null в методах с этой сигнатурой, и, таким образом, вы никогда не нарушите безопасность типа. Raw List, с другой стороны, вы можете сделать что угодно, что, как мы все знаем, может привести к нарушению безопасности типа.

void someMethod2(List list) {
 list.add(new WeaselFurBrush());  
}
List list1 = new ArrayList<String>();
someMethod2(list1);// oops