2014-02-24 49 views
0

为了实践的目的,我试图编写一个通用方法来通过调用.toString()方法来显示ArrayList的元素。让我们假设.toString()做我想做的事情。打印任何类型的ArrayList元素的一般方法

我想出了下面在我的输入ArrayListObject类型的此解决方案:

public void printArralyList(ArrayList<Object> list){ 
    for(Object o:list){ 
     System.out.print(o.toString()); 
    } 
    System.out.println(); 
} 

但是它不会工作!

printArralyList(new ArrayList<Integer>(Arrays.asList(1,2,3,5,8,13,21))); 

的编译错误我得到的是

The method printArralyList(ArrayList<Object>) is not applicable 
for the arguments (ArrayList<Integer> 

我怎么能解决?

回答

2

ArrayList<Integer>不是ArrayList<Object>,即使IntegerObject

您需要在方法参数中使用通配符,因为您不关心泛型类型参数是什么类型。

public void printArralyList(ArrayList<?> list){ 

顺便说一句,你可以有你的方法采取List而不是ArrayList,并就没有必要换的Arrays.asListArrayList返回:

public void printArralyList(List<?> list){ 

printArralyList(Arrays.asList(1,2,3,5,8,13,21)); 

会工作。

0

你不需要泛型或通配符。所有你需要的是一个简单的方法,它没有为参数指定任何类型,这样你就可以随时传入一个ArrayList。

public void printArralyList(ArrayList list){ 
    for (Object o:list){ 
     System.out.print(o.toString()); 
    } 
    System.out.println(); 
} 
+0

这将暗示使用原始类型,并销毁此类中的所有泛型类型检查... – Marco13

0

的原因错误是由rgettman在https://stackoverflow.com/a/21996188/

解释然而,如果它是用来操练的目的,你应该考虑实行多态和programming to an interface

public static void printIterable(Iterable<?> iterable) 
{ 
    for (Object object : iterable) 
    { 
     System.out.print(object); 
    } 
    System.out.println(); 
} 

这可以通过使用一个ArrayList<Integer>参数,以及一个LinkedHashSet<JComponent>或其他任何实现Iterable接口的参数....

0

回答你的问题。

声明ArrayList不等于ArrayList。即使Integer是从Object类型层次结构中提供的。

要记住重要的一点是,当你声明Collection<String> myStrings,你告诉编译器,该变量myString可以分配指一经String类型创建和收藏集是唯一的类的实例。

Collection<Object> myObjects; 

myObjects = new ArrayList<String>(); //Exception 
myObjects = new HashSet<String>(); //Exception 
myObjects = new HashSet<Object>(); //Valid 
myObjects = new ArrayList<Object>(); //Valid 
myObjects = new ArrayList<Integer>(); //Exception 

为了解决这样的问题,JAVA提供一套Wildcars,使您可以通过这一点。

有三种类型的支持各种variances的卡。

<? extends T> - Covariance 
<? super T> - Contravariance 
<?>   - Invariance/ 

有关它们的规则称为PECS

我们要消耗列表元素,删除你应该使用协方差的编译错误。

Collection<? extends Object> myObjects; 

myObjects = new ArrayList<String>(); //Valid 
myObjects = new HashSet<String>(); //Valid 
myObjects = new HashSet<Object>(); //Valid 
myObjects = new ArrayList<Object>(); //Valid 
myObjects = new ArrayList<Integer>(); //Valid 

由于Java中的每个类是从对象传递这样<? extends>在功能上等于<?>,而这正是rgettman提出的答案

Java中的集合框架支持与generics。您应该熟悉它们才能从框架中充分受益。

一种不同的方式来解决是是从通用的方法,这样有利于:

public static <T> void printList<Iterable<T> iterable) { 

    for(T element : iterable){ 
     System.out.printf("%s ",element); 
    } 
    System.out.println(); 
} 

为什么静态的?

对静态方法的调用速度更快,此方法与任何类成员都没有关系。

什么是?

这是generic method的声明。它允许你定义泛型参数的值。 Java非常敏锐,它可以自己提取版本7中的大多数情况。

如果您使用Iterable<String>调用方法,那么如果Iterable接着是'Integer',则T的值将是String

为什么可以迭代?

Iterable是一个简单的界面,允许您使用for-each look。这意味着您将能够遍历类定义实现它的所有对象。

为什么printf?

printf函数使用Formatter,从它的好处有两个 - 在当element实例分配与空的情况下,你不会得到,如果你把它o.toString()会出现空指针异常。

缺什么?

在那个实现中仍然缺少两件事 - 输入验证 - 正确的输出格式,将用昏迷分隔元素。