Need to understand Boxing in core java - java

I cant figure out how the int 7 is consider as object in below example.
The sifer(7) is consider to be method sifer(Object o). I am not able to get it how this happened. In one of my java reference book it says Int can be boxed to an Integer and then "widened" to an object. I am not sure what that means.
>> Class A
class A { }
>> Class B
class B extends A { }
>> Class ComingThru
public class ComingThru {
static String s ="-";
static void sifer(A[] ...a2)
{
s = s + "1";
}
static void sifer(B[] b1)
{
s += "3";
}
static void sifer(Object o)
{
s += "4";
}
public static void main(String[] args) {
// TODO Auto-generated method stub
A[] aa= new A[2];
B[] ba = new B[2];
//sifer(aa);
//sifer(ba);
sifer(7);
System.out.println(s);
}
}

Since there is no sifer(int) method, the compiler will try to find the "closest match". In this case, the other 2 sifer methods take arrays as parameters, which an int clearly isn't.
The last method, sifer(Object) can be applied to any objects, including an Integer so that's the method that is used for sifer(7).
The reality is a little more complex, and the JVM will look for a matching mathod in the following order:
an identity conversion
in your case: sifer(int) but there is no such method
a widening primitive conversion
in your case: sifer(long) for example, but there is no such method
a widening reference conversion
in your case: not applicable, int is not an object
a boxing conversion optionally followed by widening reference conversion
in your case that's what's happening: int is boxed to Integer which is widened to Object
an unboxing conversion optionally followed by a widening primitive conversion
in your case: not applicable

1. Above code provides an classic example of Method Overloading, along with AutoBoxing and Auto-UnBoxing which came by Java 1.5, cause manual Boxing and Unboxing was a pain.
2. The sifer(A[]... a2) and sifer(B[] b1) both accepts Array type Arguments in its parameter, which no way matches int. So now we are left only with sifer(Object o).
3. Now the int will be converted into Wrapper Object Integer Automatically.
You can verify it by doing this in snifer(Object o) method.
o.getClass().getName();
See this link for further details:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html

7 will be auto boxed to Integer which is an Object
Also See
java: boolean instanceOf Boolean?

Steps as below-
The int (7) was boxed to a Integer.
The Integer reference was widened to an Object (since Integer extends Object).
The sifer() method got an Object reference that actually refers to a Integer
object.

Related

Why does the new Integer act as value type int?

public static void main(String []args){
Integer a = new Integer(9);
d(a);
System.out.print(a) ;
}
public static void d(int z){
z=z+2;
}
or suppose I write
public static void main(String []args){
int a = 9;
d(a);
System.out.print(a) ;
}
public static void d(int z){
z=z+2;
}
but the output is the same for both: 9. Can anyone explain me in detail why?
Because JAVA is PASS BY VALUE not PASS BY REFERENCE.
Let us understand it this way,
Your main function has a local variable z whose scope is limited to main only
and your d function has another local variable z whose scope is limited to d only
So, in your d fucntion, you are basically creating a new integer literal 11 and putting it to local variable z whose scope is limited to d function only and not the variable z of main.
In your code with Integer a process called unboxing occurs. The Integer-instance is unboxed to a primitive int when calling your method d. See this to better understand how autoboxing and unboxing works.
As for your z=z+2 inside the method d. Java objects are passed-by-reference, but Java primitives or Immutable objects (like Strings) are passed-by-value. Since your method d has a primitive parameter int it's passed-by-value in this case. Your z=z+2 isn't returned however.
If you would add System.out.println(z); right after z=z+2 it will indeed print 11. So why isn't the a in your main-method changed to 11 and how can you accomplish this? As I mentioned, it's passed-by-value for primitives. You'll need to return the new value and set the a in the main method with it. If you change your code to this it will work:
public static void main(String []args){
int a = 9;
a = d(a);
System.out.print(a);
}
public static int d(int z){
return z+2;
}
Try it online.
As you can see, the void d is changed to int d, and we return the result of z+2. We then overwrite the value of a with this new result with a = d(a); in the main-method.
Java has a concept of AutoBoxing and Auto unboxing for primitive datatypes.
Since primitves like int, float double, long etc are technically not objects, they have their corresponding Classes which can be instantiated with the primitive value to treat them as objects.
So to reduce the pain, java automatically converts int to Integer and Integer to int where ever applicable.
If you are wondering why the addition value has not reflected, though it is an Integer object on performing addition, a new int object will be resulted. so it wont reflect directly. You can return the value from the method you call and assign to it.
Java passes variables by value, not by reference. If you think that passing an object and changing the value of its data member would work, it won't. In that case, too, a copy of that object will be passed, not the original object. The only solution is to declare the variable as static that can be changed from anywhere.
it's all because of Autoboxing and Unboxing feature of java which provide the functionality of converting primitive to object(Wrapper) type and vice-versa. for better understanding you can check here
. I hope it will clear all your doubts.

Return type is not returning as int when we perform unboxing

I am using autoboxing and unboxing in Java. Return type for Autoboxing is fine. no issues. but for unboxing the return type is coming as Integer instead of int. please find my coding on below and please let me know please
package JavaLearning;
public class NumberLearning {
public static void main(String[] args) {
Integer x=5; // AutoBoxing
System.out.println(x.getClass().getName()); // Display the type with the package name
System.out.println(x);
x=x+5; // Unboxing
System.out.println(x.getClass().getName()); // Display the type with the package name
System.out.println(x);
}
}
Output:
java.lang.Integer
5
java.lang.Integer
10
It's coming as Integer because you are storing the result of x+5 to x which is an Integer, so boxing occurs again.
To see that type is an int you should print directly the type of the expression x+5 but you can't do it, since it's unboxed to an int and you can't invoke a method on a primitive type.
The variable x is declared to be Integer. So in the line x = x + 5; it is automatically reboxed. If you want to avoid it, use int y = x + 5;. But remember that you cannot call .getClass() on primitive types.
Your problem is that Integer x keeps the object reference and is never assigned to a primitive.
This should give you a proper unboxing
int newX = x + 5;
Converting an object of a wrapper type (Integer) to its corresponding
primitive (int) value is called unboxing. 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.
Source
First of all, the type of a variable is fixed. In your example, the type of x is java.lang.Integer, and it cannot change into int.
The test you are doing is not valid; you'll never see the type of x change to anything else than java.lang.Integer.
When you do x = x + 5;, then a number of things are happening:
The x on the right side of the = is unboxed to int
The value 5 is added
The result of the + operation is boxed again into an Integer and assigned to x

What is difference between wrapper and Auto Boxing/Unboxing in java?

A Wrapper Class is used to convert primitive into object and object into primitive. Similarly by using Autoboxing and Unboxing we can do the same then what is the difference in these two:
1-Concept wise
2-Code wise???
Auto-boxing and auto-unboxing is just the compiler silently helping you create and use primitive wrapper objects.
For example, the int primitive type has wrapper class called Integer. You wrap and unwrap as follows:
int myInt = 7;
// Wrap the primitive value
Integer myWrappedInt = Integer.valueOf(myInt);
// Unwrap the value
int myOtherInt = myWrappedInt.intValue();
With auto-boxing and auto-unboxing, you don't have to do all that boiler-plate stuff:
int myInt = 7;
// Wrap the primitive value
Integer myWrappedInt = myInt; // Compiler auto-boxes
// Unwrap the value
int myOtherInt = myWrappedInt; // Compiler auto-unboxes
It's just a syntactic sugar, handled by the compiler. The generated byte code is the same.
Wrapper classes in java provides a mechanism to convert primitive into object and object into primitive. Whereas automatic boxing and unboxing allows you to do that conversion automatically. Autoboxing and auto unboxing are legal in java since Java 5.
public class Main {
public static void main(String[] args) {
int x=100;
Integer iob;
iob=x;//illegal upto JDK1.4
iob= Integer.valueOf(x); //legal=> Boxing,Wrapping
iob=x; //Legal since JDK1.5=> Auto Boxing
}
}
Here x is a primitive variable, iob is a reference variable. So only an address can be assigned into this iob reference. iob=Integer.valueOf(x) will convert primitive integer into integer object. This conversion can be implied as wrapping. iob=x will do the same thing. It also saves a lot of coding.
public class Main {
public static void main(String[] args) {
Integer iob= new Integer(100);
int x;
x=iob;//illegal upto JDK1.4
x=iob.intValue(); //unboxing,unwrapping
x=iob; //legal since JDK1.5=> auto unboxing
}
}
Here iob.intValue() will take the value of integer object and it will assign that value into x. x=iob does the same thing except you don't need to write conversion code.

Null, primitive data value and wrapper class in method call [duplicate]

This question already has answers here:
Why is the default type of Java integer literals int instead of long? [closed]
(7 answers)
Closed 7 years ago.
I have following code snippet
public class Sample {
public static void main(String[] args) {
test(1);//fine & output - int
test(1L);//fine & output - long
//test(null); fine & output - Integer
test(12233333333);//error
}
static void test(int a){
System.out.println("int");
}
static void test(Integer a){
System.out.println("Integer");
}
static void test(long a){
System.out.println("long");
}
static void test(Long a){
System.out.println("Long");
}
static void test(List<Integer> a){
System.out.println("List");
}
}
My question is,
Why number value always refer int(primitive type) but null refer the most specific method among the overloads?
Why we need to say implicitly 1L why it not taking long value if u give big number(1233333333333)?
Can u some one explain those?
Why number value always refer int(primitive type) but null refer the
most specific method among the overloads?
Because by default compiler refers to the 32-bit integer operation for number without suffix l OR L (for long).
Why we need to say implicitly 1L why it not taking long value if u
give big number(1233333333333)? Can u some one explain those?
As I said above it by default refers to the integer operation and for such a big number it is out of the range of the Integer as this number will be considered as integer without suffix l or L so it will refer to the method which takes int as parameter but error comes up that value is out of range.
Let's see what JLS says..
JLS 4.2
If an integer operator other than a shift operator has at least one
operand of type long, then the operation is carried out using 64-bit
precision, and the result of the numerical operator is of type long.
If the other operand is not long, it is first widened (§5.1.5) to type
long by numeric promotion (§5.6).
Otherwise, the operation is carried out using 32-bit precision, and
the result of the numerical operator is of type int. If either operand
is not an int, it is first widened to type int by numeric promotion.
1233333333333 is an int literal so you could use that but you would have to cast it to long in which case the compiler will do the conversion. It does not work because it is too large to be an int.
The reason the compiler cannot just assume it is long is because ithey would be inconsistent with 123 being an int.

Var-arg of object arrays vs. object array -- trying to understand a SCJP self test question

I'm having trouble understanding this question, and the explanation of the answer for an SCJP 1.6 self test question. Here is the problem:
class A { }
class B extends A { }
public class ComingThru {
static String s = "-";
public static void main(String[] args) {
A[] aa = new A[2];
B[] ba = new B[2];
sifter(aa);
sifter(ba);
sifter(7);
System.out.println(s);
}
static void sifter(A[]... a2) { s += "1"; }
static void sifter(B[]... b1) { s += "2"; }
static void sifter(B[] b1) { s += "3"; }
static void sifter(Object o) { s += "4"; }
}
What is the result? The answer is -434, but what throws me off is the book's explanation. It is vastly different than how the concept was explained earlier in the chapter.
"In general, overloaded var-args
methods are chosen last. Remember that
arrays are objects. Finally, an int
can be boxed to an Integer and then
"widened" to an Object."
Splitting that up, can someone please further define that explanation?
In general, overloaded var-args methods are chosen last.
Arrays are objects (I actually get that, but why is that relevant to this question).
An int can be boxed to an Integer and then "widened" to an Object.
Thanks!
The book is trying to explain why the first two overloads are never selected: because the var-args marker ... makes them be used only if every other possible overload fails. In this case, this doesn't happen -- the two sentences starting with "Remember" is explaining WHY it doesn't happen, why other possible overloads exists in the first and last case (the second case and its match with the 3rd overload of sifter is obvious): an array is an object, and an int can be boxened then widened to an Object, so the 4th overload matches the first and last ones of the calls to sifter.
When attempting to determine which method to invoke, the compiler first looks for non vararg method (e.g. sifter(Object)) before considering a vararg one (e.g. sifter(A[]...)), when both of the methods belong to the same class (more or less).
Since an array is an Object, the invocation of sifter(aa) will match sifter(Object), hence not even considering sifter(A[]...).
Starting from Java 5, the compiler may "box" primitive, i.e. convert primitive values (e.g. int) to their corresponding Object (e.g. Integer). So for sifter(6), the compiler converts the int 6 into an Integer 6, thus it would match the sifter(Object) method.

Categories

Resources