The Java language specification claims in: 8.8.7.1 Explicit Constructor Invocations .... "If an anonymous class instance creation expression appears within an explicit constructor invocation statement, then the anonymous class may not refer to any of the enclosing instances of the class whose constructor is being invoked." Helpfully it gives an example: "For example: class Top { int x; class Dummy { Dummy(Object o) {} } class Inside extends Dummy { Inside() { super(new Object() { int r = x; }); // error } Inside(final int y) { super(new Object() { int r = y; }); // correct } } } " Notice the word 'error' in the comment. This example compiles without error and produces the correct code. In what sense is it an 'error'? It is not a compiler error, it is not a runtime error. To quote Douglas Adams "this must be some new meaning of the word 'error' with which I am unfamiliar". Any idea what's gone wrong?
In article <gepkhr$rop$1$8302bc10@news.demon.co.uk>, Anon <blackhole@nowhere.com> wrote: > The Java language specification claims in: > 8.8.7.1 Explicit Constructor Invocations [<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8. 7.1>] > Notice the word 'error' in the comment. This example compiles without > error and produces the correct code. In what sense is it an 'error'? [...] Upon instantiation, I get an error trying to refer to this.x: 4: non-static variable this cannot be referenced from a static context <sscce> class Top { int x; public static void main(String[] args) { new Inside(); } class Dummy { Dummy(Object o) {} } class Inside extends Dummy { Inside() { super(new Object() { int r = x; }); // error } Inside(final int y) { super(new Object() { int r = y; }); // correct } } } </sscce> -- John B. Matthews trashgod at gmail dot com http://home.roadrunner.com/~jbmatthews/
John B. Matthews wrote: > Upon instantiation, I get an error trying to refer to this.x: Odd. My IDE (NetBeans) gives no error and runs it fine. What version on the JDK are you using? Mine is 1.6.0. Here's my SSCCE, because I needed a main method. The original source has been reformatted by my IDE, but it's just a cut and paste from the source in the OP, with an added main() method and testIt(). package jlserrortest; class Top { int x; class Dummy { Dummy( Object o ) { } } class Inside extends Dummy { Inside() { super( new Object() { int r = x; } ); // error } Inside( final int y ) { super( new Object() { int r = y; } ); // correct } } public static void main (String ... args ) { new Top().testIt(); } private void testIt() { Inside i1 = new Inside(); Inside i2 = new Inside( 10 ); System.out.println( "hash: " + (i1.hashCode() + i2.hashCode()) ); } } init: deps-jar: Created dir: C:\Users\Dev\misc\JLSErrorTest\build\classes Compiling 1 source file to C:\Users\Dev\misc\JLSErrorTest\build\classes compile: run: hash: 11276738 BUILD SUCCESSFUL (total time: 1 second)
On 4 Nov, 18:12, "John B. Matthews" <nos...@nospam.invalid> wrote: > In article <gepkhr$rop$1$8302b...@news.demon.co.uk>, > > =A0Anon <blackh...@nowhere.com> wrote: > > The Java language specification claims in: > > 8.8.7.1 Explicit Constructor Invocations > > [<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8. > 7.1>] > > > Notice the word 'error' in the comment. This example compiles without > > error and produces the correct code. In what sense is it an 'error'? > > [...] > > Upon instantiation, I get an error trying to refer to this.x: > > 4: non-static variable this cannot be referenced from a static context Quite correct you have not created an enclosing instance of Top therefore it attempts to use 'this' as the enclosing instance when you create Inside. You can't use 'this' in a static method. (main is static). Try 'new Top().new Inside();' instead of 'new Inside();' > > <sscce> > class Top { > =A0 =A0int x; > =A0 =A0public static void main(String[] args) { > =A0 =A0 =A0 new Inside(); > =A0 =A0} > =A0 =A0class Dummy { > =A0 =A0 =A0 Dummy(Object o) {} > =A0 =A0} > =A0 =A0class Inside extends Dummy { > =A0 =A0 =A0 Inside() { > =A0 =A0 =A0 =A0 =A0super(new Object() { int r =3D x; }); // error > =A0 =A0 =A0 } > =A0 =A0 =A0 Inside(final int y) { > =A0 =A0 =A0 =A0 =A0super(new Object() { int r =3D y; }); // correct > =A0 =A0 =A0 } > =A0 =A0}} > > </sscce> >
In article <geq614$gbb$1@registered.motzarella.org>, Mark Space <markspace@sbcglobal.net> wrote: > John B. Matthews wrote: > > > Upon instantiation, I get an error trying to refer to this.x: > > Odd. My IDE (NetBeans) gives no error and runs it fine. What version > on the JDK are you using? Mine is 1.6.0. > > > Here's my SSCCE, because I needed a main method. The original source > has been reformatted by my IDE, but it's just a cut and paste from the > source in the OP, with an added main() method and testIt(). Ah, thank you. On 1.5.0_16, NetBeans 6.1, using your sscce, I get the same result. The main in my sscce instantiated Inside directly, in a static context: public static void main(String[] args) { new Inside(); } This version, more like yours, compiles & runs fine: public static void main(String[] args) { new Top(); } I suspect this is not the error the OP & JLS mention. [...] -- John B. Matthews trashgod at gmail dot com http://home.roadrunner.com/~jbmatthews/
In article <c684c650-8017-4bd5-920b-819b9b940522@q26g2000prq.googlegroups.com>, Scott.Clive.A@googlemail.com wrote: > On 4 Nov, 18:12, "John B. Matthews" <nos...@nospam.invalid> wrote: > > In article <gepkhr$rop$1$8302b...@news.demon.co.uk>, > > > > �Anon <blackh...@nowhere.com> wrote: > > > The Java language specification claims in: > > > 8.8.7.1 Explicit Constructor Invocations > > > > [<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8. > > 7.1>] > > > > > Notice the word 'error' in the comment. This example compiles without > > > error and produces the correct code. In what sense is it an 'error'? > > > > [...] > > > > Upon instantiation, I get an error trying to refer to this.x: > > > > 4: non-static variable this cannot be referenced from a static context > > Quite correct you have not created an enclosing instance of Top > therefore it attempts to use 'this' as the enclosing instance when you > create Inside. You can't use 'this' in a static method. (main is > static). > > Try 'new Top().new Inside();' instead of 'new Inside();' Thanks, I see what you mean. I saw "this" and thought "this.x". I guess the OP's question remains. -- John B. Matthews trashgod at gmail dot com http://home.roadrunner.com/~jbmatthews/
When it's a jar, of course! -Wayne
![]() |
0 |
![]() |
On 4 Nov, 22:44, "John B. Matthews" <nos...@nospam.invalid> wrote: > In article > <c684c650-8017-4bd5-920b-819b9b940...@q26g2000prq.googlegroups.com>, > > > > =A0Scott.Cliv...@googlemail.com wrote: > > On 4 Nov, 18:12, "John B. Matthews" <nos...@nospam.invalid> wrote: > > > In article <gepkhr$rop$1$8302b...@news.demon.co.uk>, > > > > =A0Anon <blackh...@nowhere.com> wrote: > > > > The Java language specification claims in: > > > > 8.8.7.1 Explicit Constructor Invocations > > > > [<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#= 8.8. > > > 7.1>] > > > > > Notice the word 'error' in the comment. This example compiles witho= ut > > > > error and produces the correct code. In what sense is it an 'error'= ? > > > > [...] > > > > Upon instantiation, I get an error trying to refer to this.x: > > > > 4: non-static variable this cannot be referenced from a static contex= t > > > Quite correct you have not created an enclosing instance of Top > > therefore it attempts to use 'this' as the enclosing instance when you > > create Inside. You can't use 'this' in a static method. (main is > > static). > > > Try 'new Top().new Inside();' instead of 'new Inside();' > > Thanks, I see what you mean. I saw "this" and thought "this.x". > > I guess the OP's question remains. > > -- > John B. Matthews > trashgod at gmail dot comhttp://home.roadrunner.com/~jbmatthews/ I wonder if there's a security hole here? Here's an example based on the problem. Think you understand scope? Try this: class Top { class Inside extends Dummy { Inside() { super(new Object() { Top t =3D Top.this; class W{Top t =3D Top.this;} }); } } } class Dummy { Dummy(Object o) {} } This gives an error "4: no enclosing instance of type Top is in scope" but the error is for class W. Remove the reference to Top.this from W and it compiles fine. So Top.this is in scope in the directly enclosing class of W but not W! W is not declared in a static context so this must contradict scoping rules somewhere. Of course the anonymous class is not supposed to have access to an instance of Top because its declared in a static context - that would resolve the contradiction.
On 5 Nov, 07:46, Wayne <nos...@all.4me.invalid> wrote: > When it's a jar, of course! > > -Wayne How about when its a compiler error! class Top { int m() {return 42;}; class Inside extends Dummy { Inside() { super(new Object() { int x=3Dm(); /*class W{int x=3Dm();}*/ }); } } } class Dummy { Dummy(Object o) {} } That compiles fine. Yet "15.12.4.1 Compute Target Reference (If Necessary) ..... Otherwise, let T be the enclosing type declaration of which the method is a member, and let n be an integer such that T is the nth lexically enclosing type declaration (=A78.1.3) of the class whose declaration immediately contains the method invocation. Then the target reference is the nth lexically enclosing instance (=A78.1.3) of 'this'. It is a compile-time error if the nth lexically enclosing instance (=A78.1.3) of 'this' does not exist. ...." T corresponds to Top, n is 2. [What it's doing it looking at each enclosing class and trying to find the corresponding enclosing instance of that class.] "8.1.3 ... An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances. However, if I is immediately declared within a static method or static initializer then I does have an enclosing block, which is the innermost block statement lexically enclosing the declaration of I." "A statement or expression occurs in a static context if and only if the innermost method, constructor, instance initializer, static initializer, field initializer, or explicit constructor invocation statement enclosing the statement or expression is a static method, a static initializer, the variable initializer of a static variable, or an explicit constructor invocation statement (=A78.8.7)." super(new Object() { int x=3Dm();}); is an explicit constructor invocation statement. Therefore there are no lexically enclosing instances, therefore it is a compile-time error. So why does it compile without an error? Uncomment the code for W and you'll see that unlike the anonymous class, it is able to give a compile-time error. It determines that an instance of Top is not in scope - yet it is supposedly in scope in the directly enclosing class.
Scott.Clive.A@googlemail.com wrote: > class Top { > class Inside extends Dummy { > Inside() { > super(new Object() { Top t = Top.this; class W{Top t = > Top.this;} }); > > This gives an error "4: no enclosing instance of type Top is in scope" > but the error is for class W. Remove the reference to Top.this from W I think that's because W is a local class and implicitly static, which has no enclosing instance. See: <http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3> I can't find the section on use of "this" keyword right now, and my search fu is weak apparently. But that's my guess.
On 5 Nov, 20:47, Mark Space <marksp...@sbcglobal.net> wrote: > Scott.Cliv...@googlemail.com wrote: > > class Top { > > =A0 =A0class Inside extends Dummy { > > =A0 =A0 =A0 =A0 =A0 =A0Inside() { > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0super(new Object() { Top t =3D T= op.this; =A0 class W{Top t =3D > > Top.this;} }); > > > This gives an error "4: no enclosing instance of type Top is in scope" > > but the error is for class W. Remove the reference to Top.this from W > > I think that's because W is a local class and implicitly static, which > has no enclosing instance. See: > > <http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.1.3= > Nice try but it's easy to prove that W is not implicitly static. If it was implicitly static you would not be able to access instance methods or fields in the anonymous class. Just add an instance field to the anonymous class, you'll have no difficulty accessing it from W. The class which is implicitly static is the anonymous class (that's because it is created inside the super( ) call). The problem is Javac doesn't handle that properly, there is no enclosing instance of Top or Inside (because its implicitly static) therefore access to any instance member in either of those classes by the anonymous class ought to give a compile time error. W actually has the correct behaviour - according to the Java Language specification. The problem is the anonymous class. [BTW W is defined as a member of the anonymous class and is therefore an inner member class rather than a local class. Local classes are local to a method, constructor or initializer]. > > I can't find the section on use of "this" keyword right now, and my > search fu is weak apparently. =A0But that's my guess.