Why is Java picking this overload over the other - java

Could anyone explain to me why Java is picking the second overload instead of the first?
public static void foo (int a, double b, double...c) {}
public static void foo (double...a) {}
public static void bar ()
{
// this is the second
foo(1);
}
I thought when I pass 1 as the argument, Java would have picked the first argument because int is more specific than double?
Thanks

The second method is the only one that can match. You have only 1 argument. The first foo has at least two required: an int and a double, so that can't match.
The second foo matches because any number of numbers can match. Java will implicitly promote your int 1 to a double so it can match, with method invocation conversion.

Related

How to pass an arbitrary number of the same type arguments to a method using varargs?

These arguments are specified by three dots after the type. but i don't know what mean of ... in the method
public static void printNumberOfArguments(int... numbers) {
System.out.println(numbers.length);
}
and also in documentation
public static void method(long.. vararg) { /* do something */ }
this is wrong i don't know why?
It's possible to pass an arbitrary number of the same type of arguments to a method using the special syntax named varargs (variable-length arguments). These arguments are specified by three dots after the type. In the body of the method, you can process this parameter as a regular array of the specified type.
Your method takes an integer vararg parameter and outputs the number of arguments in the standard output using the length property of arrays.
... is a special syntax used here to specify a vararg parameter.
i am trying to provide you both types or passing varargs in methods in java:
incorrect example:
public static void method(double... varargs, int a) { /* do something */ }
The correct version of the method is:
public static void method(int a, double... varargs) { /* do something */ }
A variable-length argument is specified by three periods(…).
you can invoke the method passing several integer numbers or an array of ints. these some examples will help you to understand this:
printNumberOfArguments(1);
printNumberOfArguments(1, 2);
printNumberOfArguments(1, 2, 3);
printNumberOfArguments(new int[] { }); // no arguments here
printNumberOfArguments(new int[] { 1, 2 });
This code outputs:
1
2
3
0
2

type conversion at method calling

public class Demo1{
public static void main(String[] args){
show('A','A');
}
public static void show(char c, long a){
System.out.println("long-char");
}
public static void show(char c, int a){
System.out.println("char-int");
}
}
Output : char-int
But when I change the order of parameters in the first show() method (replacing
public static void show(char c, long a){} with public static void show(long a, char c) {}), I get a compilation error.
The compiler says that it is an ambiguous method call, because it is.
The general approach taken for overload resolution is to find the most specific applicable method, given the number and types of the actual parameters.
In the first case, the two methods have char as their first parameter; so it is only down to choosing whether the int or long overload is more specific, given that the actual parameter is a char: it is the int overload which is more specific, because int is narrower than long.
In the second case, one method has char as the first parameter; one method has char as the second parameter. So, given that the actual parameters are both chars, one of the parameters has to be converted (widened) to invoke either of the methods.
The language spec does not define that one is more specific than the other in such a case; they are both considered equally applicable, so the method call is ambiguous, and thus is a compile-time error.

The method is ambiguous for the type Error

I am trying to understand how Overloading in JAVA works and trying to get grasp of various overloading rules that are applied in case of widening, autoboxing and varargs in JAVA. I am not able to understand what is happening in the following scenario:
package package1;
public class JustAClass {
public static void add(int a, long b) {
System.out.println("all primitives");
}
//public static void add(Integer a, long b) {
// System.out.println("Wraper int, primitive long");
//}
public static void add(int a, Long b) {
System.out.println("Primitive int, Wrapper long");
}
public static void add(Integer a, Long b){
System.out.println("All wrapper");
}
public static void main(String[] args) {
int a = 10;
Integer b = 10;
long c = 9;
Long d = 9l;
add(a,c);
add(a,d);
add(b,c);
add(b,d);
}
}
At this point, I get a compilation error at the third invocation of the add method saying The method is ambiguous for the type Error .
Why is this so? What are the rules for determining which invocation of method will work? What is exactly happening in the following case?
I feel that fourth overloaded add method should work. Please help me understand the concept behind this.
There are 3 stages to method overloading resolution. The first stage doesn't do auto-boxing/unboxing, which means methods that require boxing/unboxing of the passed parameters in order to match one of the overloaded versions of add will only be considered if no match was found that doesn't require boxing/unboxing. That's why 3 of your calls, which have a single exact match, work. Regarding add(b,c);, see below why it's ambiguous.
add(a,c); // exact match to add(int a, long b)
add(a,d); // exact match to add(int a, Long b)
add(b,c); // there is no exact match, so at least one of the passed parameters must
// be boxed or unboxed. However, by unboxing b to int or boxing
// c to Long, each of the three add methods can match, and the
// compiler doesn't know which one to prefer
add(b,d); // exact match to add(Integer a, Long b)

Overloading methods

I saw below question posted on this site.
"What happens when we pass int arguments to the overloading method having float as a parameter for one method and another having double param".
I thought I understood the concept and wrote this code:
public class TestClass {
public static void main(String args[])
{
TestClass t=new TestClass();
t.sum(1/4);
}
void sum(double d)
{
System.out.println("Double==="+d);
}
void sum(int i)
{
System.out.println("Integer==="+i);
}
void sum(short s)
{
System.out.println("Short==="+d);
}
}
According to my understanding explained on this site (as mentioned above), I thought it will print Short===0, but to my surprise it prints Integer===0. Can any one explain this to me?
First of all, these are overloaded methods, not overridden methods.
1 and 4 are integers. Therefore 1/4 is an integer division, returning 0.
Therefore, the method being called is sum(int i).
sum(short s) would never be called for an int parameter, since that would require a narrowing primitive conversion (JLS 5.1.3), that may cause data loss, and is not allowed in method invocation conversion (JLS 5.3). Such a conversion can be done with an explicit cast.
If you remove the int version, sum(double d) would be called, and if you remove the double version, the code won't compile.
In order to call the short version, you must cast the parameter to short :
t.sum ((short)(1/4));
If you don't explicitly tell the compiler what are the types of 1 and 4, it assumes they are of type int. Then, / operator will apply integer division and will produce another int (which will be 0.)
After that, the method with the most specific to integer parameter type will be invoked. In your case, this will be sum(int i).
If you want to invoke some of the other overloaded methods, you will have to explicitly:
do a cast. For example, sum((short) (1/4)); will invoke sum(short s) due to the cast.
point the type of the operands. For example, sum(1d/4) will invoke sum(double d), since 1d/4 will result to double
For integer number, the type int is a default choice. So, although 1 and 4 can be defined as both int or short, since you did not defined anything, the compiler identified 1 and 4 as int and therefore it entered into the function for 1/4 division (0), which took the parameter int.

Formal and actual Arguments

As I am going through the dumps for the preparation of OCA-Level 1 I encountered one question I don't know the answer to.
If a method is defined with three arguments, when you use this method with two arguments will the third argument be null by default?
a. YES
b. NO
The code is
class overload{
int ovlDemo (int a , int b, int c){
System.out.println("hi"+ a+""+ b);
return a+b;
}
}
class EJava5{
public static void main (String args[]){
overload ab= new overload();
ab.ovlDemo(4,6,9);
}
}
For the above code it will have values 4, 6, 9
..................EDIT...................
But for this code given below has compilation error as the int c is not passed a value at ab.ovlDemo. SO i just need is confirmation that what will be third variable?
a.) Null
b.) 0
class overload{
int ovlDemo (int a , int b, int c){
System.out.println("hi"+ a+""+ b);
return a+b;
}
}
class EJava5{
public static void main (String args[]){
overload ab= new overload();
ab.ovlDemo(4,6);
}
}
If a method is defined with three arguments, when you use this method with two arguments will the third argument be null by default?
As worded, the question is nonsensical, because you can't 'use this method with two arguments'. The compiler won't let you. The question of null-ness at runtime doesn't arise, because you can't get to run-time.
The answer is therefore 'no', but not for any of the reasons given.

Categories