Strange type inference behavior of Collections.emptyList() and/or Java generic methods?
collections, generics, java
Solution
But why does inserting a (admittedly redundant) cast mess things up?
Because now the expression `Collections.emptyList()` in itself isn't the target of any assignment - so what type argument should be chosen? It's better just to specify the type argument:
// Redundant here, but just as an example
List<String> alwaysEmpty = Collections.<String>emptyList();
It works the same for the conditional operator, too:
public static void main(String[] args) {
List<String> list = (args != null)
? Arrays.asList(args) : Collections.<String>emptyList();
}
Problem
This is `jdk1.7.0_04`. I was attempting to use `Collections.emptyList()` rather than `new`ing up my own empty list in a conditional: ``` List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList(); ``` but get the following error: ``` error: incompatible types List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList(); ^ required: List<String> found: List<CAP#1> where CAP#1 is a fresh type-variable: CAP#1 extends Object from capture of ? extends Object 1 error ``` I was able to figure that I needed to change things to: ``` List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.<String>emptyList(); ``` But as part of working on this I encountered the bizarre (to me, anyways) situation that: ``` List<String> alwaysEmpty = Collections.emptyList(); ``` compiles fine, but: ``` List<String> alwaysEmpty = (List<String>) Collections.emptyList(); ``` gives the following compile error: ``` error: inconvertible types List<String> alwaysEmpty = (List<String>) Collections.emptyList(); ^ required: List<String> found: List<Object> ``` What the heck?? Now I can understand that perhaps for some strange reason the use of the conditional operator is somehow blocking the type inference system from realizing that the type parameter for the `emptyList()` call should be `String` and so it needs to be explicitly specified. But why does inserting a (admittedly redundant) cast mess things up?