I came across this weird case while writing a unit test today (simplified below).
import java.util.Collection;
import java.util.Collections;
public class Test {
public static class TestClass<T> {
private final Collection<String> field = Collections.emptyList();
public Collection<String> getField(){
return this.field;
}
}
public static void main(String[] args){
// Unchecked assignment, but why?
TestClass case1 = new TestClass();
Collection<String> field1 = case1.getField();
// This is ok
TestClass case2 = new TestClass();
Collection field2 = case2.getField();
// Adding a type parameter to the class makes the unchecked assignment dissapear
TestClass<String> case3 = new TestClass<>();
Collection<String> field3 = case3.getField();
}
}
Running javac Test.java -Xlint:unchecked
(or pasting into an IDE) yields the following message:
Test.java:17: warning: [unchecked] unchecked conversion
Collection<String> field1 = case1.getField();
^
required: Collection<String>
found: Collection
1 warning
It looks like removing the generic type parameter from the class variable declaration leaves the compiler unable to infer the type of the getField()
, even though it is declared as returning a Collection<String>
. Is this a bug? If not, can someone explain why something like this is happening? I was totally thrown for a loop while debugging a Hamcrest matcher. This was the last thing I expected to be causing my problem.