2016-08-16 88 views
-1

如果我们可以使用泛型类型解决问题,Java为何提供了无界通配符。 例如在Java中使用无界通配符和泛型类型有什么区别?

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); 
     } 
    } 
} 

谁能请帮助我了解,如果方法2可以解决我们的要求,那么为什么我们需要有方法1。 意味着哪个问题可以使用无界通配符解决,并且不能使用泛型方法类型(例如方法2)来解决?

+2

您可以在方法2中将元素添加到'list';您不能在方法1中。 –

+0

谢谢@AndyTurner,但是如果添加元素是唯一的问题,那么我们可以将其更改为以下代码段 public static void methodWithType(List list){Object obj:list) {System.out.println(obj);} {System.out.println(obj); } } – MishraJi

+0

这不是唯一的问题;这只是一个问题的例子,类型变量提供了足够的信息,以便编译器可以保证安全。 –

回答

1

区别在于,在方法1中,您对列表元素的类型一无所知;您可以使用列表元素来处理它们,例如像Object s,例如

Object obj = list.get(0); 

你甚至不能增加这个要素回列表,因为没有保证该列表的泛型类型为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. 
} 

但是如果你使用一个类型,你可以这样做变量,因为编译器具有关于它从列表中取出的元素的类型信息;它可以用这个来知道它是安全的元素添加回:

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. 
} 

擦除型T仍然是Object;但是当编译器看到对T的引用时,它可以知道它与列表元素上的边界兼容。