• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Question about overriding of generic methods

 
Greenhorn
Posts: 12
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Do you know why does this code compile successfully:



but this code does not compile?



If the compiler erases the generic types, something like that should remain:



why the method is not overriden in the second example?

Thanks.
 
author
Posts: 4335
39
jQuery Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Just because type erasure happens, doesn't mean the compiler will let anything through. One feature of generics is to actually limit your ability to compile things. For example, trying to add an unrelated class to a generic List. In other words, generics let you enforce constraints at compile time that would be ignored at runtime.
 
Gesu Saguzo
Greenhorn
Posts: 12
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Scott.

Ok. I might understand that type erasure is all, but what is wrong with the code? And why first snippet is ok?
 
Ranch Hand
Posts: 115
11
IntelliJ IDE Clojure Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It seems like it is somewhat related to erasure as you point out, or at least related to the upper bound on the generic type. The following also compiles:



It looks like you can implement everything with generic type tokens or everything with the upper bounds, but you aren't allowed to mix those two.

Although this restriction doesn't seem to apply to return types:



EDIT: In the above example, I could replace V with CharSequence and it would compile just fine. String works fine for the method signature, but the body won't compile (because the typeToken is not necessarily a Class<String>). Object as a return type of course does not work.

I'm guessing this is so because you can always narrow your return type but you can't really mess with your parameter types (by narrowing or widening them).

Interesting puzzle. I'd love to get a more concrete answer to it as well.
 
Scott Selikoff
author
Posts: 4335
39
jQuery Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ah, found the rule related to this that might help everyone... JLS 8.4.2, which says:

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

  • m2 has the same signature as m1, or
  • the signature of m1 is the same as the erasure (§4.6) of the signature of m2.


  • Using this, it should be clear why the first code snippet compiles and the second does not.

    Note: This is a pretty special case unlikely to be on the OCP exam. In other words, the exam writers aren't this mean!
     
    Marshal
    Posts: 28177
    95
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I've been lurking on this thread but I had nothing to say so I didn't post. But now I see the answer (and yes, given that it's clear why the OP's examples do or don't compile) I was mystified as to why it isn't sufficient to require only

    m2 has the same signature as m1



    in that section of the JLS, but it goes on to explain why:

    The notion of subsignature is designed to express a relationship between two methods whose signatures are not identical, but in which one may override the other. Specifically, it allows a method whose signature does not use generic types to override any generified version of that method. This is important so that library designers may freely generify methods independently of clients that define subclasses or subinterfaces of the library.



    I must say it's nice when a specification comes with an explanation of why it's necessary.

     
    Gesu Saguzo
    Greenhorn
    Posts: 12
    1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I want to thank to all of you for your great explanations and "reexplanations".

    Highly appreciated.

    Issue is clear now.

     
    Saloon Keeper
    Posts: 15484
    363
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Learn something new every day! A round of cows.
     
    Sheriff
    Posts: 9707
    43
    Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    A really nice question indeed. While the JLS explains why this is compiling, I don't understand why they did it that way.

    JLS wrote:The notion of subsignature is designed to express a relationship between two methods whose signatures are not identical, but in which one may override the other. Specifically, it allows a method whose signature does not use generic types to override any generified version of that method. This is important so that library designers may freely generify methods independently of clients that define subclasses or subinterfaces of the library.


    I can understand this being allowed if you are inheriting raw version of a library which now has generics added. So for example this class written in JDK 1.4 should compile and run on > JDK 5:

    Of course this will compile as I'm implementing raw version of Comparable, so parameter to compareTo would be Object. But as soon as I declare my class as Generic, the compiler should enforce me to implement Comparable of that type

    The above code compiles fine. I'm wondering why because, A) will there be any backward compatibility problems if it's not allowed (the class is already using Generics, so shouldn't it use Generics properly in implementing methods as well?), B) this can create confusion if I add another compareTo method which takes Employee instance

    Here the compareTo(Employee emp) is just an overloaded method. If I create some instances of Employee<Employee>, add them to a list and sort the list, the compareTo(Object) method will be called:

    So if I'm sorting the list the compareTo(Object) method is called, but if call the method directly with another Employee instance, then compareTo(Employee) is called which can be confusing...
    reply
      Bookmark Topic Watch Topic
    • New Topic