JDK-4689050 : implicit outer instance for constructing inner class: how is it selected?
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Future Project
  • OS: solaris_8
  • CPU: generic
  • Submitted: 2002-05-21
  • Updated: 2010-08-18
  • Resolved: 2010-08-18
Related Reports
Relates :  
Relates :  
Description
A subtle point regarding how the language selects the implicit outer instance
for an inner class creation expression has arisen in the context of compiler
bugs 4635044 and 4494653.  The JLS disagrees with every Java language 
implementation that I could find, and I suggest that we consider changing the 
language specification instead of all the compilers (and perhaps any user code 
and test cases that depend on the compilers current behavior).  I have tested 
javac 1.2, javac 1.3 and later, EDG's compiler, jikes, and the aspectj compiler.
The all fail the following two test cases in precisely the same way.  Based on
the current wording in the JLS, the diagnostic generated by the compiler for
4494653 is misleading.

The current wording is in 15.9.2 selects the nearest enclosing instance of which
the class being created is a member.  Existing compilers, on the other hand,
select the nearest enclosing class that is a subtype of the type containing the
class being created.  There is only a difference when the class being created
is not inherited either because of protection or because it is hidden.  It is
unfortunate that the Java language is defined in such a way that a distinction
between these two choices is possible.  The two enclosed test cases, based on
the current JLS2 wording, illustrate these issues.  All compilers fail them.

While the specification is clear in this regard, I wonder if it would not be
better to change the language specification to bring it in line with current
practice rather than the other way around.  In order to address the related
compiler bugs, I will need a definitive statement one way or another on whether
the JLS2 will be adjusted.


/** Check that non-inheritance (private) prevents enclosing class selection. */
class T1 {
    boolean isT() { return true; }
    private class Middle extends T1 {
        boolean isT() { return false; }
        boolean enclIsT() { return T1.this.isT(); }
        class Inner {}
        boolean check() {
            return /*T1.this.*/new T1.Middle().enclIsT();
        }
    }
    public static void main(String[] args) {
        T1 t = new T1();
        Middle m = t.new Middle();
        if (!m.check()) throw new Error();
    }
}

/** Check that hiding prevents enclosing class selection. */
class T2 {
    boolean isT() { return true; }
    class Middle {
        boolean enclIsT() { return T2.this.isT(); }
    }
    class X extends T2 {
        boolean isT() { return false; }
        class Middle {} // hide T2.Middle
        boolean check() {
            return /*T2.this.*/new T2.Middle().enclIsT();
            // error: javac uses X.this instead of T2.this, above
        }
    }
    public static void main(String[] args) {
        T2 t = new T2();
        X x = t.new X();
        if (!x.check()) throw new Error();
    }
}

Comments
PUBLIC COMMENTS ...
21-07-2004

EVALUATION It seems to me that the implementations are uniformly buggy. Would their behavior make sense if Middle were a field? The notion of enclosing instances is based on lexical scope. Changing this would be fundamentally wrong. The spec should not be changed. ###@###.### 2002-05-24 See also 4689058. It seems that the specifications are uniformly buggy ;-) Fields cannot be accessed without respect to an instance; an appropriate outer is selected when the field name is looked up. A qualified type name, on the other hand, is not resolved locally. ###@###.### 2002-06-04 After I implemented the compiler changes needed to comply with the JLS text (4635044 and 4494653) we observed a significant compatibility regression (4787017). Please reconsider this issue for compatibility reasons. ###@###.### 2002-12-02
02-12-2002