Search code examples
javacompiler-errorskeywordjava-17

Eclipse gives "Illegal modifier for the local class (class); only abstract or final is permitted" whereas IntelliJ allows it


There is some code of the form below that gives the error:

Illegal modifier for the local class MyList; only abstract or final is permitted

However, this only appears to happen in Eclipse (version 2024-12 (4.34.0)) and not in javac or IntelliJ. Java 17 is being used.

Eclipse seems to be objecting to the keyword private being used against the inner class. It is not clear to me whether this is Eclipse being over-zealous, or the other compilers being over-lax or maybe I have some setting that is not aligned. If you remove private the error goes away, but this isn't my code.

Any ideas? Is this legal or not?

Note that he code below is just designed to show the error. It isn't supposed to do anything.

import java.util.ArrayList;
import java.util.Iterator;

public class IllegalModifier {

    private Iterator<String> someMethod() {
        
        return new Iterator<String>() {
            // Gives "Illegal modifier for the local class MyList; only abstract or final is permitted"
            private static class MyList extends ArrayList<String> {
                public MyList() {
                    super();
                    add("n");
                }
            }
            
            @Override
            public boolean hasNext() {
                return false;
            }

            @Override
            public String next() {
                return null;
            }
        };
    }
}

Solution

  • This is a bug in the Eclipse Java compiler. The bug has been reported here and is not resolved at the time of writing.

    In your case, the compiler mistakes MyList as a local class, which it certainly is not. From the language specification,

    A local class is a nested class (§8) whose declaration is immediately contained by a block (§14.2).

    MyList is not immediately contained by a block. It is immediately contained by the anonymous class declaration new Iterator<String>() { ... }. The pair of curly braces here is not a block (which is a kind of statement), but a class body.

    MyList here is just an inner class of the anonymous class, and inner classes can certainly be private, and they can also be static since Java 16.

    Side note: since MyList is an inner class of the anonymous class, it is very hard to access even without being private, so private here doesn't have much of an effect.