通用列表打印方法

8
我正在尝试编写一个通用的打印方法,可以适用于所有实现“Iterable”接口的类。
public class List<T> {

    public static <T extends Iterable<T>> void print(T[] list){
        for (Object element : list){
            System.out.println(element);
        }
    }
    public static void main(String[] args){
        ArrayList<Integer> l = new ArrayList();
        l.add(1);
        l.add(5);
        l.add(3);
        l.add(2);
        print(l);
    }
}

但是我收到了错误信息:“List中的print(T[])方法不适用于参数(ArrayList)”


你可能不想将你的类命名为 List。此外,在 class List<T> 中的 Tpublic static <T extends Iterable<T>> void print(T[] list) 中的 T 不同。 - GriffeyDog
4个回答

7
您的参数是T[],它是一个类型为Iterable的数组。您只需要T。但是您还需要一个类型变量来表示Iterable中的类型参数。
public static <T extends Iterable<E>, E> void print(T list) {

你需要这个是因为你不想要一个Iterable<ArrayList>,而这正是你当前实现的情况。


7
我认为print(Iterable<?>)也可以,除非我读得太快了。 - Paul Bellora
@PaulBellora 是的,你说得对。这也可以(在这种情况下可能更好)。玩泛型很有趣。 - Sotirios Delimanolis

4

您的通用定义不正确。您正试图将边界设置为<T extends Iterable<T>>,但泛型参数(Integer)不是T

您可以通过引入单独的泛型参数来使其工作:一个用于指示集合,另一个用于指示集合的值。

附注:您根本不需要T[]。您只需要T

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> l = new ArrayList<>();
        l.add(1);
        l.add(5);
        l.add(3);
        l.add(2);
        print(l);
    }

    public static <S, T extends Iterable<S>> void print(T list){
        for (Object element : list){
            System.out.println(element);
        }
    }
}

输出

1
5
3
2

3

由于 System.out.println 接受所有的 Object,而且在方法内部并没有真正使用泛型,所以我看不出任何必要使用泛型。以下代码将实现相同的功能:

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

你已经做了什么

我还想补充一点,你把T[]搞得有点混淆了。 T[]的意思是"类型为T的数组"。但是你正在尝试传递一个ArrayList参数,它不同于一个数组(类ArrayList内部使用常规数组,但这与问题无关)。

让我们看一下你原来的方法声明:

public static <T extends Iterable<T>> void print(T[] list) {
    for (Object element : list) {
        System.out.println(element);
    }
}

这个方法被声明为接受一个参数:一个泛型类型为 T 的数组,其中泛型类型 T 可以对泛型类型 T 进行迭代。

让我们再读一遍最后一部分:其中泛型类型 T 可以对泛型类型 T 进行迭代。

也就是说,泛型类型应该可以对自身进行迭代。

您需要像这样的一个类来使用您当前的print方法:

class MyClass implements Iterable<MyClass> {
    ...
}

然后像这样使用您的打印方法:

MyClass[] objects = new MyClass[5];
print(objects);

然而,使用您当前的打印方法,它只会对数组中的每个元素调用MyClass.toString方法。


0
如果 T 继承自 Iterable,那么只需要这样做:
public static <E, T extends Iterable<E>> void print(T list){
        for (Object element : list){
            System.out.println(element);
        }
}

编辑:你声明的是 T extends Iterable<T>,这可能是 Iterable 等类型,这可能不是你想要实现的目标。然后只需添加列表元素的另一种类型。

如果你不需要特定的类型,那么也可以将泛型类型声明为:

<T extends Iterable<?>>

它也无法编译。 - Rohit Jain
是的,我只是更仔细地看了一下他的泛型定义,这可能不正确。 - Kuba Spatny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接