-1

Why Java has provided Unbounded wild card if we can solve the problem using Generic type . For example

class UnBoundedUsage {

     //Method 1
     public static void unboundedMethod(List<?> list) {
        for(Object obj : list) {
           System.out.println(obj);
        }
     }

     //Method 2
     public static <T> void methodWithType(List<T> list) {
        for(T obj : list) {
           System.out.println(obj);
        }
     }
}

Can anyone please help me understand if Method 2 can solve our requirement then why do we need to have Method 1 . Means , which problem can be solved using Unbounded wildcard and that cannot be solved using Generic method Type (e.g Method 2) ?

MishraJi
  • 304
  • 2
  • 6
  • 18
  • 2
    You can add elements to `list` in Method 2; you can't in Method 1. – Andy Turner Aug 16 '16 at 13:48
  • Thanks @AndyTurner but if addition of element is the only issue then we can change it to below code snippet public static void methodWithType(List super T> list) { for(Object obj : list) { System.out.println(obj); } } – MishraJi Aug 16 '16 at 13:56
  • It's not the only issue; it's just an example of an issue that the type variable provides enough information so that the compiler can guarantee safety. – Andy Turner Aug 16 '16 at 13:57
  • Thanks @AndyTurner .. Got the answer from your 'Answer' post – MishraJi Aug 16 '16 at 14:15

1 Answers1

1

The difference is that in Method 1, you know nothing about the type of the list elements; all you can do with the list elements is to treat them like Objects, e.g.

Object obj = list.get(0);

You can't even add this element back into the list, since there is no guarantee that the list's generic type is Object:

List<Integer> list = new ArrayList<>(Arrays.asList(1));
method1(list);

void method1(List<?> list) {
  Object obj = list.get(0);
  list.add(obj);  // Compiler error! Can't add an Object to the List.
}

But you can do this if you use a type variable, since the compiler has type information about the elements it gets out of the list; and it can use this to know that it is safe to add the element back:

List<Integer> list = new ArrayList<>(Arrays.asList(1));
method2(list);

<T> void method2(List<T> list) {
  T obj = list.get(0);
  list.add(obj);  // OK!

  // But, if you discard the type information...
  Object obj1 = list.get(0);
  list.add(obj1);  // Still a compiler error.
}

The erased type of T is still Object; but when the compiler sees a reference to a T, it can know that it is compatible with the bounds on the list's elements.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243