12 Replies Latest reply: Jan 17, 2013 9:05 AM by 984357 RSS

    Generics question

    984357
      Hi, I have a question regarding generics if anyone has time...? The following code prints "C". Why does it do that? B and C are not related. The Generic class
      is instantiated with B as type argument, while the operation m is invoked with an instance of C.X. Thanks!
      class A {
        class X { 
          void print() {} 
        }
      }
       
      class B extends A {
        class X extends A.X { void print() {} }  
      }
       
      class C extends A {
        class X extends A.X  { 
          void print() {
            System.out.println( "C" );     
          }
        }
      }
       
      class Generic<E extends A> {
        void m( E.X x ) {
          x.print();
        }
      }
       
      public class Main {
        public static void main( String[] args ) {
          Generic<B> g = new Generic<B> ();
          
          A a = new C();
          A.X x = ((C)a).new X();
          g.m( x ); // Prints "C"
        }
      } 
      Edited by: 981354 on Jan 15, 2013 2:33 AM
        • 1. Re: Generics question
          jtahlborn
          981354 wrote:
          Hi, I have a question regarding generics if anyone has time...? The following code prints "C". Why does it do that? B and C are not related. The Generic class
          is instantiated with B as type argument, while the operation m is invoked with an instance of C.X. Thanks!
          A.X x = ((C)a).new X();
          you are instantiating a specific class instance here, "C.X". the print() method of "C.X" prints "C". what did you expect to happen?
          • 2. Re: Generics question
            984357
            Hi,

            Yes, but the C class is not a subtype of the B class. So shouldn't there be a compilation error here?
            • 3. Re: Generics question
              jtahlborn
              981354 wrote:
              Hi,

              Yes, but the C class is not a subtype of the B class. So shouldn't there be a compilation error here?
              well, your code doesn't compile for me in java 6, so yes, i'd say there was an error here. what version of java are you using?
              • 4. Re: Generics question
                TPD-Opitz
                981354 wrote:
                Yes, but the C class is not a subtype of the B class. So shouldn't there be a compilation error here?
                No because C.X is extending B.X and this is extending A.X.
                The relatinship of the containing classes does not matter, the inner classes have a family tree of their own.

                bye
                TPD
                • 5. Re: Generics question
                  rp0428
                  >
                  No because C.X is extending B.X and this is extending A.X.
                  >
                  No it isn't - it extends A.X.
                  • 6. Re: Generics question
                    984357
                    Sorry if you had problems executing the code - it should work now!

                    Any new insight on this?
                    • 7. Re: Generics question
                      800268
                      Looks like the compiler resolves E.X as A.X not your expected B.X. Makes sense as <E extends A> provides no guarantee that A.X will also be extended and that that class will be named X as well, so it really can only mean A.X.

                      If you want specifics you'll have to look at the Java specification.
                      • 8. Re: Generics question
                        rp0428
                        >
                        Sorry if you had problems executing the code - it should work now!
                        >
                        You didn't answer the question that was asked: what version of Java (javac) are you using?

                        The code posted doesn't compile in 1.6
                        >
                        method m in class Generic<E> cannot be applied to given types
                        required: B.X
                        found: A.X
                        • 9. Re: Generics question
                          984357
                          Well, I just copied the code from this website, made a new project and the code compiles fine (1.6.0_35). Strange!
                          • 10. Re: Generics question
                            abillconsl
                            I had to change
                            void m(E.X x) {
                            to
                            void m(A.X x) {
                            in order to get a clean compile.
                            • 11. Re: Generics question
                              800268
                              Ah, I used the Eclipse Juno compiler

                              JDK7u7 gives (note I actually renamed B.X to B.Y here in the source, but it still wants a B.X ><):
                              TestGenerics.java:34: error: method m in class Generic<E> cannot be applied to given types;
                                  g.m( x ); // Prints "C"
                                   ^
                                required: B.X
                                found: A.X
                                reason: actual argument A.X cannot be converted to B.X by method invocation conversion
                                where E is a type-variable:
                                  E extends A declared in class Generic
                              JDK6u30 gives:
                              TestGenerics.java:23: cannot select from a type variable
                                void m( E.X x ) {
                                         ^
                              • 12. Re: Generics question
                                984357
                                Thanks guys!

                                Then it appears that there's an issue with the compiler version I'm using.