• 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

Generics and Method Overriding

 
Ranch Hand
Posts: 64
4
Eclipse IDE C++ Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Suppose we have the following classes

and some code that uses them

in each case, which method is invoked first, the bridge method or the typed method? Which method is the one that is actually overriding Foo#foo(T) (aka Foo#foo(Object))?
My logical guess is that the synthetic method is called first and is the actual overriding method, for its method signature matches its superclass's method signature, but I'm not sure what the JVM really does. Would bar.foo(42) and foo.foo(42) call the same method, or would bar.foo(42) call the typed method to avoid the overhead of having to "go over the bridge"?
 
Ranch Hand
Posts: 233
1
Eclipse IDE Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You have instance methods in there, so the execution depends completely upon the instance present in those variables with which you are invoking the methods in runtime.
In your code, both 'bar' and 'foo' variables will have 'Bar' instance in runtime and so that class's method will be invoked.

If Bar overrides Foo's foo(), then in both cases Bar's foo() will be invoked.
Example:

The output will be:

foo in Bar
foo in Bar



Now consider below code where foo is not actually overridden:


The output will be :

foo in Bar
foo foo


The driver code is:
 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Very interesting question. Awarding a cow for it because I found out a few things looking up information about this.

So, it seems to me that a couple of things come into play here:
1. static vs dynamic binding
2. Type erasure and polymorphism.

Refer to https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html

The synthetic/bridge method is generated by the compiler to preserve the polymorphism of generic types after type erasure. That seems to indicate to me that the bridge only gets involved when static binding happens at compile time. Or maybe not. Normally, polymorphism involves dynamic binding so if the correct method to execute is determined at runtime, I would think that there would be no need to go through the bridge method. But then again, the dynamic binding goes by the method signature and only the synthetic bridge method has the signature that matches the one in the parent class after type erasure. I'm just writing this stuff as I think about it so excuse the flipflopping. The more I think about it though the more I tend to agree with the original guess that the polymorphic call goes through the synthetic bridge. The bridge would not be involved if binding happens statically to the subclass method with the specific type.

Another thing to consider is that a ClassCastException will be thrown at runtime. That would be happening in the synthetic method, which I guess would be the result of static binding(?). Anyway, I haven't tried any of this myself but you might try throwing a runtime exception somewhere strategic so you can look at the stack trace and see if the synthetic method was involved in the call. You'll probably have to put the throw inside an if statement that checks a non-final variable in its condition so your code will compile.

Another article that this question led me to was this: http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Rajdeep, I haven't looked into your example deeply but on the surface, your code is different from what the compiler would provide in a synthetic method after type erasure so I doubt the same mechanisms are in play.
 
Rajdeep Biswas
Ranch Hand
Posts: 233
1
Eclipse IDE Opera Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes Junilu, I need to check in that synthetic code stuff, never came across earlier. I just explained in a simple fashion, probably missed this concept that I'm yet to learn or know about.
 
Louis Denning
Ranch Hand
Posts: 64
4
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Having a look at the stack trace upon calling each method, bar.foo(42) calls the typed method and foo.foo(42) [probably] calls the overriding bridge method.
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Louis Denning wrote:Having a look at the stack trace upon calling each method, bar.foo(42) calls the typed method and foo.foo(42) [probably] calls the overriding bridge method.


I would say that the stack trace leaves no doubt that the call through the Foo reference that was assigned a Bar instance went through the synthetic bridge.

I guess it's dynamic binding all the way then.
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
For the curious, here's how you would print the stack trace:
 
Louis Denning
Ranch Hand
Posts: 64
4
Eclipse IDE C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I wonder how Java 10 will change things up when [and if] they decide to implement type reification and reified generics.
 
Let's go to the waterfront with this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic