Collections.emptyList() returns a List?

I’m having some trouble navigating Java’s rule for inferring generic type parameters. Consider the following class, which has an optional list parameter:

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;
  }
}

My Java compiler gives the following error:

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

But Collections.emptyList() returns type <T> List<T>, not List<Object>. Adding a cast doesn’t help

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

yields

Person.java:9: inconvertible types

Using EMPTY_LIST instead of emptyList()

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

yields

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

Whereas the following change makes the error go away:

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

Can anyone explain what type-checking rule I’m running up against here, and the best way to work around it? In this example, the final code example is satisfactory, but with larger classes, I’d like to be able to write methods following this “optional parameter” pattern without duplicating code.

For extra credit: when is it appropriate to use EMPTY_LIST as opposed to emptyList()?

4 Answers
4

Leave a Comment