We can not declare constructors in anonymous classes. But If I need to initialize the state of the objects of an anonymous classes with the value of, say, local variables, how would I do that?
-
I don't see how this question is opinion based. It's purely technical as I see it. Nominating for reopen.aioobe– aioobe2015-01-28 11:27:51 +00:00Commented Jan 28, 2015 at 11:27
-
Himaloy, welcome to stackoverflow. Since you're new to this site, you may want to read this.aioobe– aioobe2015-02-02 14:27:07 +00:00Commented Feb 2, 2015 at 14:27
3 Answers
You can do as follows:
final int localVar = 5;
new Runnable() {
int innerVar = localVar; // <--- initialized here
public void run() {
System.out.println(innerVar);
}
}.run();
If localVar is mutated (not final) you can work around it using
...
final int tmp = localVar;
new Runnable() {
int innerVar = tmp;
...
...
Also note that you can use instance initializers if you need to call methods or do other initialization what you would usually do in a constructor:
final int localVar = 5;
new Runnable() {
int innerVar;
// Initialization block executed upon construction of this class
{
System.out.println("Initializing an anonymous Runnable");
innerVar = localVar;
}
public void run() {
System.out.println(innerVar);
}
}.run();
See for instance: Why java Instance initializers?
6 Comments
Your assumption that we cannot use constructors to create anonymous classes is not entirely correct. This is only the case if the anonymous class is created from an interface (which cannot have constructors). See my example below:
public class Main {
public static class Razzy {
private final String name;
public Razzy(final String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(final String[] args) {
final Razzy anonymous = new Razzy("Award") {
@Override
public String getName() {
return "Anonymous " + super.getName();
}
};
System.out.println(anonymous.getName());
}
}
Here the class Razzy has a constructor taking a String. In the main method an anonymous subclass of Razzy is created, using this single argument constructor.
The output is:
Anonymous Award
In this way you can pass a local variable into the constructor of an anonymous class.
Note that anonymous classes can also access the fields of their enclosing class:
public class Main {
private static String input = "Award";
public interface Razzy {
public String getName();
}
public static void main(final String[] args) {
final Razzy anonymous = new Razzy() {
@Override
public String getName() {
return "Anonymous " + input ;
}
};
System.out.println(anonymous.getName());
}
}
Has the same output.
2 Comments
The thing is, you don't actually need to define a constructor. An anonymous class implicitly has access to any variables in the scope of the enclosing method. They only need to be declared final (in Java 8, the final keyword is not needed, but you still can't reassign a value to them).
public void enclosingMethod() {
final int localVariable = 42; // final is necessary
Runnable r = new Runnable() {
public void run() {
// look ma, no constructors!
System.out.println(localVariable);
}
};
r.run(); // prints 42
}