JDK-6886402 : Parameterized inner classes and subclassing
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: x86
  • Submitted: 2009-09-29
  • Updated: 2024-04-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :


A DESCRIPTION OF THE PROBLEM :
$ javac -J-showversion -fullversion Test3.java
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b71)
Java HotSpot(TM) Client VM (build 16.0-b08, mixed mode, sharing)

javac full version "1.7.0-ea-b71"
$ java -showversion Test3
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b71)
Java HotSpot(TM) Server VM (build 16.0-b08, mixed mode)

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
        at Test3.testInnerClassWithMismatchedOuterType(Test3.java:26)
        at Test3.main(Test3.java:30)
$ cat -n Test3.java
     1  import java.util.*;
     2
     3  class Test3 {
     4   static class ListHolder<T> {
     5     final List<T> list = new ArrayList<T>();
     6
     7     class Inserter {
     8       Inserter(T itemToAdd) {
     9         list.add(itemToAdd);
    10       }
    11     }
    12   }
    13
    14   static class StringListHolder extends ListHolder<String> {
    15     class IntInserter extends ListHolder<Integer>.Inserter {
    16       IntInserter() {
    17         super(42);
    18       }
    19     }
    20   }
    21
    22   public void testInnerClassWithMismatchedOuterType() {
    23     StringListHolder list = new StringListHolder();
    24     list.new IntInserter();
    25
    26     System.out.println(list.list.get(0).length());
    27   }
    28
    29    public static void main(String... args) {
    30      new Test3().testInnerClassWithMismatchedOuterType();
    31    }
    32  }
    33


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The program should fail to compile.
ACTUAL -
The program compiles and causes a class cast exception.

REPRODUCIBILITY :
This bug can be reproduced always.

Comments
EVALUATION In both the 'super' and 'new' cases, it's worth noting that the correct behavior may be to match a class in which the false positive is nested: static class IntListHolder extends ListHolder<Integer> { class StringListHolder extends ListHolder<String> { class IntInserter .. } }
31-03-2011

EVALUATION We also need to fix the similar handling of class instance creations -- replace class IntInserter in the example above with: { new ListHolder<Integer>.Inserter(42); } And the same problem arises.
31-03-2011

EVALUATION The specification is confusing. See bug 7026147. Clearly, though, the program is unacceptable. One way to read the spec is that ListHolder<Integer>.Inserter and ListHolder<String>.Inserter are different classes, even though they share a declaration (just like the type of the method List<Integer>.add is different from the type of the method List<String>.add). In that case, ListHolder<Integer>.Inserter is not a member of StringListHolder, and so there is no suitable enclosing instance for the super call.
09-03-2011