2

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?

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • I don't see how this question is opinion based. It's purely technical as I see it. Nominating for reopen. – aioobe Jan 28 '15 at 11:27
  • Himaloy, welcome to stackoverflow. Since you're new to this site, you may want to read [this](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – aioobe Feb 02 '15 at 14:27

3 Answers3

5

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?

Community
  • 1
  • 1
aioobe
  • 413,195
  • 112
  • 811
  • 826
3

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.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60
  • OP does not say that you can't use a constructor to create an anonymous class. OP says that you can't declare a constructor in an anonymous class, which I agree with (since the constructor should have the name of the class and since an anonymous class has no name.) – aioobe Jan 15 '15 at 13:36
  • Ah yes, now I see what OP meant. My answer still offers a way to initialize an anonymous class with the value of non-final local variable. – Adriaan Koster Jan 15 '15 at 13:39
0

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
}
Natix
  • 14,017
  • 7
  • 54
  • 69