Strange syntax for instantiating an inner class

前端 未结 6 1825
慢半拍i
慢半拍i 2020-12-05 09:12

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

相关标签:
6条回答
  • 2020-12-05 09:54

    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.

    0 讨论(0)
  • 2020-12-05 09:59

    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.

    0 讨论(0)
  • 2020-12-05 10:06

    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.

    0 讨论(0)
  • 2020-12-05 10:07

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

    0 讨论(0)
  • 2020-12-05 10:11

    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.

    0 讨论(0)
  • 2020-12-05 10:16

    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) {
        }
    }
    
    0 讨论(0)
提交回复
热议问题