8 Replies Latest reply: Feb 22, 2010 3:52 AM by EJP RSS

    Why the following doesn't compile

    843793
      Can someone explain me why the following doesn't compile:
      class A<N extends Number> {
          public LinkedList<String> list;
      
          public N getN() {
              return null;
          }
      }
      
      class Test {
          Test(A a) {
              Number n = a.getN();
              String str = a.list.getFirst();
          }
      }
      The compiler error is:
      incompatible types
      found   : java.lang.Object
      required: java.lang.String
              String str = a.list.getFirst();
      And if compiler "lose" generic info for some reason or other, so it don't know type "a.list.getFirst()" anymore and think that it's Object, then why it know type of "a.getN()"?
        • 1. Re: Why the following doesn't compile
          jtahlborn
          when you use "raw types" in a given class, the compiler drops all generics in the class. this is for backwards compatibility. in your case, since you have a raw A in "Test(A a)", generics are being disabled for the Test class.
          • 2. Re: Why the following doesn't compile
            843793
            ah, i see...
            thanks you

            PS. but why there is no way to enable generics globally, e.g. why compiler switch "-source" does not affect this...
            • 3. Re: Why the following doesn't compile
              DrClap
              I'm not convinced by that explanation. I've used List<Whatever> in classes which aren't themselves generic and it works as I and the OP expect it to work. And I don't really see the difference between a class which isn't generic and a class which could be generic but isn't. I also don't see why public members should be treated differently when accessed from outside a class compared to when accessed inside a class.

              If it indeed doesn't compile (and I haven't tested that myself) then no doubt there's a reason for that, this isn't one of those convoluted examples which the compiler writers could have missed without anybody noticing. It just doesn't seem to me that what jtahlborn wrote is actually the reason.
              • 4. Re: Why the following doesn't compile
                843793
                btw,
                jtahlborn wrote:
                in your case, since you have a raw A in "Test(A a)", generics are being disabled for the Test class.
                i guess you mean it's "disabled" only for this variable, and not for the whole class
                coz the compiler think that in following code there is nothing wrong in "String strb = b.list.getFirst();"
                public class Test {
                    Test(A a, A<?> b) {
                        Number n = a.getN();
                
                        String strb = b.list.getFirst();
                        String stra = a.list.getFirst();
                    }
                }
                • 5. Re: Why the following doesn't compile
                  843793
                  and even more oddly:
                  public class Test {
                      Test(A a, B b, A<?> c) {
                          Number n = a.getN();
                  
                          String strb = b.list.getFirst();// ok
                          String strc = c.list.getFirst();// ok
                          String stra = a.list.getFirst();// error
                      }
                  }
                  
                  class A<N extends Number> {
                      public LinkedList<String> list;
                  
                      public N getN() {
                          return null;
                      }
                  }
                  
                  class B {
                      public LinkedList<String> list;
                  
                      public Number getN() {
                          return null;
                      }
                  }
                  • 6. Re: Why the following doesn't compile
                    843793
                    getFirst return object and you are assigning in string so it is error
                    • 7. Re: Why the following doesn't compile
                      EJP
                      No. List<String>.getFirst() returns a String, not an Object.
                      • 8. Re: Why the following doesn't compile
                        800353
                        DrClap wrote:
                        I'm not convinced by that explanation. I've used List<Whatever> in classes which aren't themselves generic and it works as I and the OP expect it to work. And I don't really see the difference between a class which isn't generic and a class which could be generic but isn't. I also don't see why public members should be treated differently when accessed from outside a class compared to when accessed inside a class.

                        If it indeed doesn't compile (and I haven't tested that myself) then no doubt there's a reason for that, this isn't one of those convoluted examples which the compiler writers could have missed without anybody noticing. It just doesn't seem to me that what jtahlborn wrote is actually the reason.
                        Jtahlborn was correct with his explanation: whenever you use a generic type as the corresponding "raw type", the type loses all its generic features.
                        Thus, the public member "list" loses its parameter of type String and becomes the raw type "List"
                        The method "getN" loses its return type +"N extends Number"+ and yields simply a "Number".

                        For a detailed discussion, see [http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#110257]