Strange syntax for instantiating an inner class

Henrik Paul picture Henrik Paul · Mar 11, 2009 · Viewed 16.8k times · Source

I didn't imagine that I would encounter radically new syntax in Java anymore at this stage, but lo and behold, I just encountered something:

The exact context and what the code below should do is pretty irrelevant - it's there just to give some kind of context.

I'm trying to synthetically create an event in IT Mill Toolkit, so I wrote this kind of line:

buttonClick(new Button.ClickEvent(button));

But, Eclipse gives me the following error message:

No enclosing instance of type Button is accessible. Must qualify the allocation with an enclosing instance of type Button (e.g. x.new A() where x is an instance of Button).

When I rewrite the line above as follows, it doesn't complain anymore:

buttonClick(button.new ClickEvent(button)); // button instanceof Button

So, my question is: What does the latter syntax mean, exactly, and why doesn't the first snippet work? What is Java complaining about, and what's it doing in the second version?

Background info: Both Button and Button.ClickEvent are non-abstract public classes.

Answer

Jon Skeet picture Jon Skeet · Mar 11, 2009

Inner classes (like Button.ClickEvent) need a reference to an instance of the outer class (Button).

That syntax creates a new instance of Button.ClickEvent with its outer class reference set to the value of button.

Here's an example - ignore the lack of encapsulation etc, it's just for the purposes of demonstration:

class Outer
{
    String name;

    class Inner
    {
        void sayHi()
        {
            System.out.println("Outer name = " + name);
        }
    }
}

public class Test
{
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        outer.name = "Fred";

        Outer.Inner inner = outer.new Inner();
        inner.sayHi();
    }
}

See section 8.1.3 of the spec for more about inner classes and enclosing instances.