Search code examples
javaintellij-ideajava-11java-17

Why this code snippet produces `error: incompatible types: ArrayList<String> cannot be converted to <anonymous ArrayList<String>>`?


public class AnonymousAssign {

    public static void main(String[] args) {
        new AnonymousAssign().testAnonymousAssign();
    }

    public void testAnonymousAssign() {
        var list1 = new ArrayList<String>() {{
            add("");
        }};
        list1 = new ArrayList<String>(); // this line produces an error
        System.out.println(list1.getClass()); // print `class AnonymousAssign$1`

    }
}
 error: incompatible types: ArrayList<String> cannot be converted to <anonymous ArrayList<String>>
        list1 = new ArrayList<String>();

Why is var assign make such type inference and not allow a seemingly straightforward and reasonable value reassignment ?


Some more infos

System.out.println(list1.getClass()); would print class AnonymousAssign$1

but not a class java.util.ArrayList


Below is a tip from IntelliJ IDEA's 2022.3, it isn't meaningful. ide's tip does not seems useful



Solution

  • The expression

    new ArrayList<String>() {{
            add("");
        }};
    

    creates an instance of an anonymous sub-class of ArrayList<String>. Therefore the inferred type of it is a sub-class of ArrayList, so you can't assign an instance of ArrayList to it later (unless that instance was also of the same sub-class of ArrayList, which is not possible, since it's an anonymous sub-class).

    If you want the type of the variable to be ArrayList, you'll have to explicitly declare it so:

    ArrayList<String> list1 = new ArrayList<String>() {{
            add("");
        }};
    

    or even better:

    List<String> list1 = new ArrayList<String>() {{
            add("");
        }};
    

    Now the second assignment will work.