Why does adding a public field to an anonymous class in Java not work?

You're creating an object of type foobar. The compiler only knows about the members defined for the class/interface foobar.

Remember, java is a static language, not dynamic. It doesn't check the object at runtime for what exists, it checks at compile time based on the type declaration.


A local class would do

{
    class MyFooBar extends FooBar{
        String name = null;
        ...
    };

    MyFooBar fooBar = new MyFooBar();

    fooBar.name = "Test";
}

Try this.

@SafeVarargs
public static <T> void runWithObject(T object, Consumer<T>... progs) {
    for (Consumer<T> prog : progs)
        prog.accept(object);
}

and

runWithObject(
    new FooBar() {
        String name = null;
        @Override
        void method1(Foo foo) {
            System.out.println("name=" + name);
        }
    },
    object -> object.name = "Test",
    object -> object.method1(new Foo())
);

result:

name=Test

Or you can use var like this in Java 10 or later.

var fooBar = new FooBar() {
    public String name = null;

    @Override
    void method1(Foo foo) {
        System.out.println("name=" + name);
    }
};
fooBar.name = "Test";
fooBar.method1(new Foo());

Because the type of the variable "fooBar" is FooBar (the run-time type of the object in said variable is that of the anonymous class implementing FooBar which is also a subtype of FooBar)...

...and the type FooBar does not have said member. Hence, a compile error. (Remember, the variable "fooBar" can contain any object conforming to FooBar, even those without name, and thus the compiler rejects the code which is not type-safe.)

Edit: For one solution, see irreputable's answer which uses a Local Class Declaration to create a new named type (to replace the anonymous type in the post).

Java does not support a way to do this (mainly: Java does not support useful type inference), although the following does work, even if not very useful:

(new foobar(){
  public String name = null;
  @Override
  void method1(Foo foo){
    ...
  }
}).name = "fred";

Happy coding.


Both Scala and C# support the required type inference, and thus anonymous type specializations, of local variables. (Although C# does not support extending existing types anonymously). Java, however, does not.