有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java是打印任何类型的ArrayList元素的通用方法

出于实践目的,我试图编写一个通用方法,通过调用.toString()方法来显示ArrayList的元素。让我们假设.toString()做了我希望它做的事情

我在下面提出了这个解决方案,其中我的输入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>

我怎样才能解决这个问题


共 (4) 个答案

  1. # 1 楼答案

    一个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));
    

    会有用的

  2. # 2 楼答案

    RGETMAN在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. # 3 楼答案

    回答你的问题

    声明ArrayList不等于ArrayList。即使从类型层次结构中的Object传递了一个Integer

    需要记住的重要一点是,当您声明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>在功能上等于<?>,这就是Targetman提出的答案

    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>调用该方法,则T的值将为String如果是Iterable,则为“Integer”

    为什么不可忍受

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

    为什么是printf

    printf函数使用Formatter,它有两个好处 -当element的实例被赋值为null时,如果调用它o.toString(),将不会出现null指针异常

    少了什么

    在这方面,实现仍然缺少两件事 -输入验证 -正确的输出格式,将使用coma分隔元素

  4. # 4 楼答案

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

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