Why doesn't adding a public field to an anonymous class in Java work?

I have an example class defined below:

public class FooBar { void method1(Foo foo){ // Should be overwritten ... } } 

Later when I try this:

 FooBar fooBar = new FooBar(){ public String name = null; @Override void method1(Foo foo){ ... } }; fooBar.name = "Test"; 

I get a message that the name field does not exist. Why?

+10
java anonymous-class
source share
8 answers

Since the type of the variable "fooBar" is FooBar (the FooBar type of the object in the specified variable corresponds to the implementation type of the anonymous class FooBar , which is also a subtype of FooBar ) ..

... and the type FooBar does not have a specified member. Therefore, a compilation error. (Remember that the variable "fooBar" can contain any object matching FooBar , even those that do not have a name , and therefore the compiler rejects code that is not type safe.)

Edit: for one solution, see the unique answer that uses the "Local Class Declaration" to create a new named type (to replace the anonymous type in the message).

Java does not support the way to do this (basically: Java does not support useful type inference), although the following works even if it is 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 of output, and thus anonymous types of specialized local variables. (Although C # does not support anonymous distribution of existing types). Java, however, does not.

+11
source share

Local class will do

 { class MyFooBar extends FooBar{ String name = null; ... }; MyFooBar fooBar = new MyFooBar(); fooBar.name = "Test"; } 
+7
source share

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()); 
+1
source share

fooBar is a reference to an object of type fooBar , and such objects do not have a name field. Just like that. And since this is an anonymous type, the only way to refer to this field is via the this link.

0
source share

An object of type foobar . The compiler only knows about the members defined for the foobar class / interface.

Remember that java is a static language, not a dynamic one. It does not check the object at runtime for what exists, it checks compilation time based on the type declaration.

0
source share

fooBar type fooBar , which does not have such a variable, so the code cannot be compiled. You can access it by reflection.

0
source share

As everyone said, this is due to the static type, and the FooBar class FooBar not contain name . So this will not work.

I wanted to point out the proposed use of the Anonymous class.

An anonymous class (or close to Closures, possibly lambdas. Similar, but not the same) comes from the functional programming paradigm, where states must be unchanged.

Saying why you should use such classes? When you need a short and short thing to do that doesn't have to go in full class. Example:

 MyTask() //This is a method { new Thread(new Runnable() { //Anonymous class public void run() {} }).start(); } 

Understanding the inclusion of your implementation only in a function / class is important.

scope of the variables defined in the Anonymous class (or closed-over function) should only be used inside the Anonymous class , it cannot be accessed from other program code.

Therefore, you should not (and in any case cannot) set fooBar.name = "Test";

0
source share

You can also do it as follows

 Boolean var= new anonymousClass(){ private String myVar; //String for example @Overriden public Boolean method(int i){ //use myVar and i } public String setVar(String var){myVar=var; return this;} //Returns self instane }.setVar("Hello").method(3); 
0
source share

All Articles