• Post Reply Bookmark Topic Watch Topic
  • New Topic

How compiler picks what method to execute?  RSS feed

 
Maria Kowalczyk
Greenhorn
Posts: 15
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


This code prints long.
Why is that? How did compiler decided that it likes long version of foo() method the most.
If I had to guess I'd pick int... or possibly Integer as they are most similiar to what was passed.
But why long?
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The language considers long to be the most specific match, because it's a primitive, and it's not variable arity. The compiler simply prefers widening operations over boxing, and I believe varargs comes very last.

That's just how it is. The most important lesson you should take from this is: don't write classes that have confusing overloaded methods. It might have been better to name the varargs version fooAll(), or something.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maria Kowalczyk wrote:

This code prints long.
Why is that? How did compiler decided that it likes long version of foo() method the most.
If I had to guess I'd pick int... or possibly Integer as they are most similiar to what was passed.
But why long?


There are two rules that apply here...

First, if more than one method match, the compiler will try to look for the "most specific" method. How that works is... let's say two methods match, now, which is the most specific? The answer is... if you take the parameters of one of the methods, and can use it to call the the other method, and it works (without explicit casting), but the reverse doesn't work, then that method is more specific than the other -- and it gets chosen.

Second, for backward compatibility, not all options are tried straight away. It is done in three passes. The first pass only uses typing. The second pass uses method conversion (which doesn't include varargs). And the third pass uses everything.

So... using the second rule. On the first pass, the only method that matches is the one that takes a long, as autoboxing and var-args don't apply yet. And since, there is only one match, no need to look for the more specific.

Henry
 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The reason widening takes precedence over boxing and var-args is backwards compatibility. The latter two have only been around since Java 5, so code written before the Java 5 release will still behave in the same manner when this rule is applied.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maria Kowalczyk wrote:If I had to guess I'd pick int......

Which is why you should never guess. EVER.

And the best way to do that, as Stephan said, is not to write overloaded methods if you can help it. Then the compiler doesn't have to make a choice, and you don't have to guess.

The fact is that most of the rules are specified in the JLS, here - but I warn you: it's dry reading, and there's a LOT to it.

It might also be worth mentioning that if you really make the choice difficult, the compiler may simply pick the first method defined.

Winston
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!