代码之家  ›  专栏  ›  技术社区  ›  waxwing

list.toarray的奇泛型行为(t[])

  •  23
  • waxwing  · 技术社区  · 15 年前

    今天我遇到了一些非常基本但非常困惑的事情。我需要将列表转换为数组。包含的列表 String 实例。使用的完美例子 List.toArray(T[]) 因为我想要一个 String[] 实例。但是,如果不将结果显式地强制转换为 字符串[ ] .

    作为测试场景,我使用了以下代码:

    import java.util.Arrays;
    import java.util.List;
    
    public class MainClass {
        public static void main(String args[]) {
            List l = Arrays.asList("a", "b", "c");
            String stuff[] = l.toArray(new String[0]);
            System.err.println(Arrays.asList(stuff));
        }
    }
    

    它不能编译。它几乎是 javadoc 但是编译器说:

    MainClass.java:7: incompatible types
    found   : java.lang.Object[]
    required: java.lang.String[]
        String stuff[] = l.toArray(new String[0]);
                              ^
    

    如果我添加演员表 字符串[ ] 它将完美地编译和运行。但当我看到toarray方法的签名时,这不是我所期望的:

    <T> T[] toArray(T[] a)
    

    这告诉我我不该投。怎么回事?

    编辑:

    奇怪的是,如果我将列表声明更改为:

    List<?> l = Arrays.asList("a", "b", "c");
    

    它也起作用。或 List<Object> . 所以不一定是 List<String> 按照建议。我开始觉得用生的 List 类型还更改该类中泛型方法的工作方式。

    第二次编辑:

    我想我现在明白了。汤姆·霍丁在下面的评论中所写的似乎是最好的解释。如果以原始方式使用泛型类型,编译器将清除该实例中的所有泛型信息。

    5 回复  |  直到 15 年前
        1
  •  29
  •   dfa    15 年前

    您忘记为列表指定类型参数:

    List<String> l = Arrays.asList("a", "b", "c");
    

    在这种情况下,您可以写安全:

    String[] a = l.toArray(new String[0]);
    

    没有任何石膏。

        2
  •  3
  •   user85421    14 年前

    或做

    List<?> l = Arrays.asList("a", "b", "c");  
    

    仍然陌生

        3
  •  1
  •   Paul Adamson    15 年前
    List<String> l = Arrays.asList("a", "b", "c");
    

    这将使它编译,您使用泛型说“这是一个字符串列表”,所以to array方法知道返回哪种类型的数组。

        4
  •  0
  •   JRL    15 年前

    这是因为您的列表包含对象,而不是字符串。你把你的名单声明为 List<String> 编译器会很高兴的。

        5
  •  0
  •   Alan Moore Chris Ballance    15 年前

    List 如果没有声明的类型,则默认为“对象列表”,而 List<?> 表示“未知列表”。在泛型类型的世界中,“对象列表”不同于“字符串列表”,但编译器不能对“未知列表”这样说。如果你已经声明了它是未知的,那么就编译器所知,这是可以的。

    主要的一点是声明一些通配符?不同于将其声明为对象。阅读有关通配符的详细信息 here