What does `someObject.new` do in Java?

后端 未结 5 1613
灰色年华
灰色年华 2020-12-23 02:47

In Java, I have just found out that the following code is legal:

KnockKnockServer newServer = new KnockKnockServer();                    
KnockKnockServer.re         


        
5条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-23 03:23

    Have a look at this example:

    public class Test {
    
        class TestInner{
    
        }
    
        public TestInner method(){
            return new TestInner();
        }
    
        public static void main(String[] args) throws Exception{
            Test t = new Test();
            Test.TestInner ti = t.new TestInner();
        }
    }
    

    Using javap we can view instructions generated for this code

    Main method:

    public static void main(java.lang.String[])   throws java.lang.Exception;
      Code:
       0:   new     #2; //class Test
       3:   dup
       4:   invokespecial   #3; //Method "":()V
       7:   astore_1
       8:   new     #4; //class Test$TestInner
       11:  dup
       12:  aload_1
       13:  dup
       14:  invokevirtual   #5; //Method java/lang/Object.getClass:()Ljava/lang/Class;
       17:  pop
       18:  invokespecial   #6; //Method Test$TestInner."":(LTest;)V
       21:  astore_2
       22:  return
    }
    

    Inner class constructor:

    Test$TestInner(Test);
      Code:
       0:   aload_0
       1:   aload_1
       2:   putfield        #1; //Field this$0:LTest;
       5:   aload_0
       6:   invokespecial   #2; //Method java/lang/Object."":()V
       9:   return
    
    }
    

    Everything is simple - when invoking TestInner constructor, java passes Test instance as a first argument main:12. Not looking at that TestInner should have a no argument constructor. TestInner in its turn just saves reference to parent object, Test$TestInner:2. When you are invoking inner class constructor from an instance method, reference to parent object is passes automatically, so you do not have to specify it. Actually its passes every time, but when invoking from outside it should be passed explicitly.

    t.new TestInner(); - is just a way to specify the first hidden argument to TestInner constructor, not a type

    method() is equal to:

    public TestInner method(){
        return this.new TestInner();
    }
    

    TestInner is equal to:

    class TestInner{
        private Test this$0;
    
        TestInner(Test parent){
            this.this$0 = parent;
        }
    }
    

提交回复
热议问题