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?

2
  • I don't see how this question is opinion based. It's purely technical as I see it. Nominating for reopen. Commented Jan 28, 2015 at 11:27
  • Himaloy, welcome to stackoverflow. Since you're new to this site, you may want to read this. Commented Feb 2, 2015 at 14:27

3 Answers 3

6

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?

Sign up to request clarification or add additional context in comments.

6 Comments

for java < 8 final is required for access localVar
Yup. Thanks. Updated.
The solution with the instance initializer does not work. It always requires a final local variable.
Works on Java 8. Answer updated anyway.
That's strange. I tried it with my compliance level at 1.8 in Eclipse and it still flagged a compile error.
|
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.

2 Comments

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.)
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.
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
}

1 Comment

seems @aioobe's answer much more detailed

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.