代码之家  ›  专栏  ›  技术社区  ›  Charles Duffy

collections.emptylist()返回一个列表<object>?

  •  246
  • Charles Duffy  · 技术社区  · 17 年前

    我在导航Java规则中遇到了一些困难,用于推断泛型类型参数。考虑下面的类,它有一个可选的列表参数:

    import java.util.Collections;
    import java.util.List;
    
    public class Person {
      private String name;
      private List<String> nicknames;
    
      public Person(String name) {
        this(name,Collections.emptyList());
      }
    
      public Person(String name,List<String> nicknames) {
        this.name = name;
        this.nicknames = nicknames;
      }
    }
    

    我的Java编译器给出以下错误:

    Person.java:9: The constructor Person(String, List<Object>) is undefined
    

    但是 Collections.emptyList() 返回类型 <T> List<T> 不是 List<Object> . 添加演员表没有帮助

    public Person(String name) {
      this(name,(List<String>)Collections.emptyList());
    }
    

    产量

    Person.java:9: inconvertible types
    

    使用 EMPTY_LIST 而不是 emptyList()

    public Person(String name) {
      this(name,Collections.EMPTY_LIST);
    }
    

    产量

    Person.java:9: warning: [unchecked] unchecked conversion
    

    但是,以下更改会使错误消失:

    public Person(String name) {
      this.name = name;
      this.nicknames = Collections.emptyList();
    }
    

    有人能解释一下我在这里遇到的是什么类型的检查规则,以及解决这个问题的最佳方法吗?在这个例子中,最后一个代码示例是令人满意的,但是对于较大的类,我希望能够按照这个“可选参数”模式编写方法,而不需要重复代码。

    额外学分:什么时候可以使用 清空表 而不是 EMPTYLIST() ?

    3 回复  |  直到 13 年前
        1
  •  418
  •   InverseFalcon    17 年前

    您遇到的问题是,即使该方法 emptyList() 收益率 List<T> ,您没有为它提供类型,因此它默认为返回 List<Object> . 您可以提供类型参数,并让您的代码按预期工作,如下所示:

    public Person(String name) {
      this(name,Collections.<String>emptyList());
    }
    

    现在,当您执行直接赋值时,编译器可以为您计算出泛型类型参数。这叫做类型推理。例如,如果您这样做:

    public Person(String name) {
      List<String> emptyList = Collections.emptyList();
      this(name, emptyList);
    }
    

    然后 EMPTYLIST() 呼叫将正确返回 List<String> .

        2
  •  92
  •   carson    17 年前

    您要使用:

    Collections.<String>emptyList();
    

    如果你在源代码中查找空列表,你会发现它实际上只做了一个

    return (List<T>)EMPTY_LIST;
    
        3
  •  26
  •   Dan Vinton    17 年前

    EmptyList方法具有以下签名:

    public static final <T> List<T> emptyList()
    

    <T> 在单词列表之前意味着它从分配给结果的变量类型推断泛型参数t的值。所以在这种情况下:

    List<String> stringList = Collections.emptyList();
    

    然后返回值由类型为的变量显式引用 List<String> ,这样编译器就可以解决这个问题。在这种情况下:

    setList(Collections.emptyList());
    

    编译器没有显式返回变量来计算泛型类型,因此它默认为 Object .