出于练习目的,我试图通过调用ArrayList
方法来编写显示.toString()
元素的通用方法。我们假设.toString()
做我想做的事。
我想出了下面的解决方案,我的输入ArrayList
的类型为Object
:
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>
我该如何解决这个问题?
答案 0 :(得分:2)
ArrayList<Integer>
不是ArrayList<Object>
,即使Integer
是Object
。
您需要在方法的参数中使用通配符,因为您不关心泛型类型参数的类型。
public void printArralyList(ArrayList<?> list){
顺便提一下,您可以让自己的方法采用List
代替ArrayList
,并且不需要在Arrays.asList
中包含ArrayList
的返回值:
public void printArralyList(List<?> list){
和
printArralyList(Arrays.asList(1,2,3,5,8,13,21));
会起作用。
答案 1 :(得分:0)
你不需要泛型或通配符。您只需要一个简单的方法,它不会为参数指定任何类型,以便您可以随时传入ArrayList。
public void printArralyList(ArrayList list){
for (Object o:list){
System.out.print(o.toString());
}
System.out.println();
}
答案 2 :(得分: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
接口的内容一起使用....
答案 3 :(得分: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提出的答案
generics支持Java中的集合框架。您应该熟悉它们以从框架中充分受益。
另一种解决方法是从这样的通用方法中受益:
public static <T> void printList<Iterable<T> iterable) {
for(T element : iterable){
System.out.printf("%s ",element);
}
System.out.println();
}
为何静电?
对static方法的调用更快,并且此方法与任何类成员无关。
是什么?
这是generic method的声明。它允许您定义泛型参数的值。 Java非常敏锐,它可以在版本7中大多数情况下自行提取它。
如果用Iterable<String>
调用方法,那么如果Iterable为“整数”,则T的值为String
。
为什么可以使用?
Iterable是一个简单的界面,可让您使用for-each look。这意味着您将能够遍历类定义实现它的所有对象。
为什么选择printf?
printf函数使用Formatter,它的好处是两个
- 如果element
的实例被赋值为null,则在调用它o.toString()
时将不会出现空指针异常。
缺少什么?
在那个实现中仍然缺少两件事 - 输入验证 - 正确的输出格式,将元素与昏迷分开。