[ https://issues.apache.org/jira/browse/GROOVY-7885?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15375605#comment-15375605 ]
Jochen Theodorou edited comment on GROOVY-7885 at 7/13/16 7:38 PM: ------------------------------------------------------------------- Short answer: NPE is maybe unexpected, newInstance not working is expected though. Longer version: In Java an inner class comes in two kinds, the static ones and the non-static ones. The static ones cannot call instance methods of the outer class, the non-static ones can. This is realized by supplying the inner class with an instance of the outer class, normally stored as this$0. This also means, that the inner class constructor you declare is not really the constructor that will be used. Instead B(){} will be transformed to something like {code}B(A x){this.this$0 = x;}{code}. This is also true for the default constructor in B. So if you want to create an instance of B, you will need an instance of A. The new-instance-operator in Java will do this for you and hide those implementation details. the newInstance-method cannot do this, since it has no access to the instance that did the call and is just a normal method. So the right way to make an instance of B is in your code B.newInstance(this). This will call the B(A) constructor Groovy generated, just the same way the java compiler would have done. If you wanted to create a newinstance of B using reflection, you would have the exact same problem. was (Author: blackdrag): Short answer: NPE is maybe unexpected, newInstance not working is expected though. Longer version: In Java an inner class comes in two kinds, the static ones and the non-static ones. The static ones cannot call instance methods of the outer class, the non-static ones can. This is realized by supplying the inner class with an instance of the outer class, normally stored as this$0. This also means, that the inner class constructor you declare is not really the constructor that will be used. Instead B(){} will be transformed to something like B(A x){this.this$0 = x;}. This is also true for the default constructor in B. So if you want to create an instance of B, you will need an instance of A. The new-instance-operator in Java will do this for you and hide those implementation details. the newInstance-method cannot do this, since it has no access to the instance that did the call and is just a normal method. So the right way to make an instance of B is in your code B.newInstance(this). This will call the B(A) constructor Groovy generated, just the same way the java compiler would have done. If you wanted to create a newinstance of B using reflection, you would have the exact same problem. > referencing method in outer class from inner class throws Exception when > using newInstance() > -------------------------------------------------------------------------------------------- > > Key: GROOVY-7885 > URL: https://issues.apache.org/jira/browse/GROOVY-7885 > Project: Groovy > Issue Type: Bug > Affects Versions: 2.4.6 > Reporter: Jörg Prante > Priority: Minor > > This code throws an error > class A { > Object o > A() { > def b = B.newInstance() > o = "Hello" > b.execute() > } > Object val() { > o > } > class B { > void execute() { > println val() > } > } > } > def a = new A() > groovy Test.groovy > Caught: java.lang.NullPointerException > java.lang.NullPointerException > at A$B.methodMissing(Test.groovy) > at A$B.execute(Test.groovy:18) > at A$B$execute.call(Unknown Source) > at A.<init>(Test.groovy:9) > at Test.run(Test.groovy:24) > but this code works > class A { > Object o > A() { > def b = new B() > o = "Hello" > b.execute() > } > Object val() { > o > } > class B { > void execute() { > println val() > } > } > } > def a = new A() > Is this expected? -- This message was sent by Atlassian JIRA (v6.3.4#6332)