Can please anybody explain me this Autoboxing? - java

Alright, here's the code :
public class Dec26 {
public static void main(String args[]) {
short a1=6;
new Dec26.go(a1);
new Dec26.go(new Integer(7));
}
void go(Short x){System.out.println("S");}
void go(Long x){System.out.println("L");}
void go(int x){System.out.println("i");}
void go(Number n){System.out.println("N");}
}
Why is the output "iN" and not "ii" ?

The Java compiler applies unboxing when an object of a wrapper class is:
Passed as a parameter to a method that expects a value of the
corresponding primitive type.
Assigned to a variable of the corresponding primitive type.
So, as there was a suitable method for Integer class, which is void go(Number n) because Number class is super class of Integer and this method accepts Integer objects as well.
So compiler didn't need to unbox the Integer to int.

Compiler chooses the closest match without autoboxing /unboxing first. It found go(Number) and did not use unboxing.

Related

How do I provide byte value specifically to a class having m1(byte) and m1(int) signatures

public class HelloWorld
{
public void m1(int i)
{
System.out.println("int-arg");
}
public void m1(byte j)
{
System.out.println("byte-arg");
}
public static void main(String []args)
{
HelloWorld n=new HelloWorld();
n.m1(12);
}
}
O/P: int-arg
Question: 12 is int type and byte type too. so in this case int is the exact match everytime. so what value should I provide if I want to call m1(byte) method?
Thanks.
You can either declare it with type or cast it
byte b = 12;
n.m1(b);
or cast
n.m1((byte)b);
As others have said, you will need to cast it.
In Java, plain numbers (ex: 12) are int by default, if the number has decimals (ex: 12.0), it will default to float double type (thank you #Sushil for the correction). There are suffixed to force some types, but not for all types (ex: 12L is long, 12.0f is float).
You'll need to cast prior to passing the value.
n.m1((byte)12);

Auto-boxing followed by Widening in Java

Following program prints Object as output, and when I remove the overloaded method contains Object as parameters, following compile time error is there:
The method m1(Long) in the type LangPackage is not applicable for the
arguments (int)
public class A {
public static void main(String args[])
{
int x = 0;
m1(x);
}
static void m1(Long l) {
System.out.println("long");
}
static void m1(Object l) {
System.out.println("Object");
}
}
My query is why auto-boxing followed by widening is allowed for Objects not for Long type
auto-boxing boxes an int to an Integer.
An Integer is an Object, but it's not a Long. Therefore static void m1(Long l) cannot be chosen.
If you would call the method with a long parameter (i.e. if x would be a long), it would be auto-boxed to Long, and static void m1(Long l) would be preferred over static void m1(Object l).
If you call m1 with a long, the output is long:
m1(1L);
If you call with an integer - m1(1) - Java will choose the method with the Object parameter.
If you change input parameter from Long to long, the output is long for m1(1):
static void m1(long l) {
This works because int and long (not Integer and Long) are primitive types and Java converts from int to long in a case like this.
Integer does not extend Long, or vice versa. But both extend Number, so if you change to:
static void m1(Number n) {
That method will be called for m1(1)
https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Autoboxing is the automatic conversion that the Java compiler makes
between the primitive types and their corresponding object wrapper
classes. For example, converting an int to an Integer, a double to a
Double, and so on. If the conversion goes the other way, this is
called unboxing.

Java varargs method overloading compiler error - ambiguity?

So, today I've been testing Java's overloading techniques and I've come across ambiguity which I can't explain. Basically, when there is a vararg method with primitive and its corresponding wrapper the compiler complains and can't decide which one to choose and I don't understand why? It's easy for human to decide and not for compiler?
Here is the fragment which works for non-vararg parameters:
public static void main(String[] args)
{
int a = 14;
Integer b = new Integer(14);
stuff(a);
stuff(b);
}
static void stuff(Integer arg) { System.out.println("Integer"); }
static void stuff(int arg) { System.out.println("int"); }
And here comes the vararg which complains and cries like a baby:
public static void main(String[] args)
{
int a = 14;
Integer b = new Integer(14);
stuff(a); // Doesn't compile (ambiguity)
stuff(b); // Doesn't compile (ambiguity)
}
static void stuff(int... arg) { System.out.println("varargs int"); }
static void stuff(Integer... arg) { System.out.println("varargs Integer"); }
Consider the following two hypothetical calls to stuff():
int a = 14;
Integer b = new Integer(14);
stuff(a, b);
stuff(b, a);
How does the compiler even know which method should be called here? Because of autoboxing rules, either call could be referring to either overloaded method.
Update:
My answer is logically correct, or at least on the right track, but for a more formal answer we can refer to this SO question:
Why ambiguous error when using varargs overloading with primitive type and wrapper class?
The two varargs method are invoked in loose invocation context. As a result, the compiler will attempt to find the more specific method via JLS 15.12.2.5 Choosing the Most Specific Method. However, since neither int nor Integer are subtypes of one another, the compiler will throw an error.
The problem is:
java is doing behind the scenes bridge methods (you need to verify that is you need deep info)
AND the important part, vargargs means too YOU CAN JUST NOT PASS ANY PARAMETER, so:
static void stuff(int... arg)
and
static void stuff(Integer... arg)
can both being invoked taking no parameters... so that will create some conflict about what method should the JVM invoke

The output of the following program is 1,3,3 can someone explain it how?

The output of the following program is 1,3,3 can someone explain it how?
will it consider 10.25 as a object to the method argument?
public class Test {
void methodOfTest(int i) {
System.out.println(1);
}
void methodOfTest(Integer I) {
System.out.println(2);
}
void methodOfTest(Object o) {
System.out.println(3);
}
public static void main(String[] args) {
Test t = new Test();
t.methodOfTest(10);
t.methodOfTest(10.25);
t.methodOfTest(new Double("25.25"));
}
}
t.methodOfTest(10);
10 is interpreted as int literal, so methodOfTest(int i) is called
t.methodOfTest(10.25);
There is no method, that takes a double, so the only method where 10.25 fits in is methodOfTest(Object o)
t.methodOfTest(new Double("25.25"));
Here we have a Double object, but again, no method is found that takes a Double, so the only method that takes this is again methodOfTest(Object o).
Therefore your output is 1,3,3.
It does not consider 10.25 to be an object. It does consider it to be assignment-convertible to an Object reference, by boxing conversion to a Double reference followed by widening reference conversion.
The boxing answers are absolutely correct.
I just wanted to add this: you were perhaps expecting an automatic (implicit) conversion from Double to Integer, but such a conversion must be declared explicitly (casting Double to Integer).
Without an explicit conversion, your Double value is interpreted as an Object (since you provided that method overload), which is the base class of about everything.
Hope this helps ;)
Because 10.25 can be converted to a Double. (boxing into Double)
So the constructor of Double will be called with 10.25 as parameter and will be passed to the method : void methodOfTest(Object o).

When I pass a null, which overloaded function will java run

So i can pass nulls into functions in java. I can also overload functions in java. But consider the following
public static void main(String ... args){
doStuff(null);
}
public static void doStuff(String s){
solveWorldHunger();
}
public static void doStuff(Integer i){
nukeCanada();
}
public static void nukeCanada(){
System.out.println("NO!");
}
public static void solveWorldHunger(){
System.out.println("YAY!");
}
The previous program will always print out YAY no matter what the order of the sorce code...
Can anyone shed some light onto why the jvm consitently decides to run the solveWorldHunger function over the nukeCanada function`?
It's quite clear to the compiler that you can't store null in a primitive int. So, it decides to go with the method which has String as argument.
However, when you change your 2nd method to take Integer as argument, then you will get compiler error. Because both of them are eligible to be invoked with null argument. So, there will be ambiguity.
So, try changing your 2nd method: -
public static void doStuff(String s){
solveWorldHunger();
}
public static void doStuff(Integer i){ // Integer instead of `int`
nukeCanada();
}
And invoke it on null. You will see the compiler error.
So, in that case, you can invoke the appropriate method using typecasting like this: -
doStuff((Integer)null); // Calls Integer version
doStuff((String)null); // Calls String version
Also, note that, if you have your 2nd method take a parameter that is a super type of String, like Object, then there would be no ambiguity, because compiler will now choose the most specific one, i.e., String argument.
So, ambiguity only occurs, when you have two methods with types that are not in the same inheritance hierarchy.
Only your doStuff(String) method can take a NULL argument... the primitive int can never be null. If you had a second method overload that passed an object, you would no longer be able to pass null as a parameter for that method.

Categories