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 a
To avoid confusing yourself and fellow programmers with this rarely-used feature you can always make inner classes static.
In case a reference to the outer class is needed you can pass it explicitly in the constructor.
Your code would compile, had you typed
buttonClick(new Button().ClickEvent(button));
instead of
buttonClick(new Button.ClickEvent(button));
as a constructor is a method and when you call a method in Java you must pass the list of arguments, even when it is empty.
A non-static inner class in Java contains a hidden reference that points to an instance of the outer class it is declared in. So the error message you got originally is telling you that you cannot create a new instance of the inner class without also specifying an instance of the outer class for it to be attached to.
Perhaps the reason you haven't seen that syntax before is that inner classes are often allocated in a method of the outer class, where the compiler takes care of this automatically.
Button.ClickEvent is a non-static inner class so an instance of this class can only exist enclosed in a instance of Button.
In your second code example you have an instance of Button and you create an instance of ClickEvent enclosed in this Button instance...
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.
You actually can do that, but you have to declare ClickEvent
as static
inside Button
, and then you shouldn't have any problem using you sintax:
buttonClick(new Button.ClickEvent(button));
Basically static
makes the class ClickEvent
belong directly to the class Button
instead of a specific instance(i.e. new Button()
) of Button
.
Following @Jon Skeet example:
// Button.java
class Button
{
public static class ClickEvent
{
public ClickEvent(Button b)
{
System.out.println("Instance: " + this.toString());
}
}
}
// Test.java
public class Test
{
public static void main(String[] args)
{
Button button = new Button();
buttonClick(new Button.ClickEvent(button));
}
public static void buttonClick (Button.ClickEvent ce) {
}
}