What is the difference between these two. I know Boxing is converting primitive values to reference. What is widening. Also what should be the sequence first boxing should be done or widening should be done?
Widening is transforming a variable in another with a wider type.
Widening can be done with primitive or reference types.
For example :
String
-> Object
int
-> long
As the JLS states :
a boxing conversion (§5.1.7) [is] optionally followed by a widening reference conversion
Resources :
- Widening wins over boxing and var-args
- Boxing wins over var-args
- Widening of reference variable depends on inheritance(so, Integer cannot be widened to Long. But, Integer widened to Number).
- Widen and boxing is not possible
- Boxing and widening is possible
- var-args can be combined with either boxing or widening
Widening is transforming a variable in another with a wider type.
Widening can be done with primitive or reference types.
For example :
String
-> Object
int
-> long
As the JLS states :
a boxing conversion (§5.1.7) [is] optionally followed by a widening reference conversion
Resources :
Widening is when assign byte
to int
. i.e. you are widening the data type.
Sequence must be boxing
then widening
.
You CANNOT widen then box (int cannot be Long).
You CAN box then widen (int can become Object via Integer)
Note: Highlighted words are from Sun Certified Java Programmer SCJP 6 - Kathy Sierra
- Widening beats boxing eg. go(int) will call go(long) instead of go(Integer) if both are available
- Widening beats var-args eg go(byte,byte) will call go(int,int) instead of go(byte...x) method.
- Boxing beats var-args eg go(byte,byte) will call go(Byte,Byte) instead of go(byte...x) method.
- widening depends on inheritance tree. Eg. go(dog) can call go(Animal)
- primitive wrapper widening is not possible so go(Short) cannot call go(Integer) since they are not in the same inheritance hierarchy .
- You CANNOT widen and then box. Eg. go(int) cannot call go(Long) since to call go(Long) the compiler need to convert int to Integer then Integer to Long which is not possible.(rule mentioned above)
- You can box and then widen. Eg. An int can boxed to Integer and then widen to Object
Widening is the extension of data type into a wider type. Boxing is when primitive data type is wrapped into a container object so that it can be used in Generics, mainly Collections. Eg:
public class Widening{
public static void main(String[] args) throws Exception {
int test = 20;
myOverloadedFunction(test);
}
//static void myOverloadedFunction(long parameter) {
//System.out.println("I am primitive long");
//}
static void myOverloadedFunction(Integer parameter) {
System.out.println("i am wrapper class Integer");
}
}
Output:
i am wrapper class Integer
(int is wrapped in Integer container)
Now lets uncomment another overloaded method and see:
public class Widening{
public static void main(String[] args) throws Exception {
int test = 20;
myOverloadedFunction(test);
}
static void myOverloadedFunction(long parameter) {
System.out.println("I am primitive long");
}
static void myOverloadedFunction(Integer parameter) {
System.out.println("i am wrapper class Integer");
}
}
Output: I am primitive long
Compiler precedence is widening over autoboxing.
Widening is transforming a primitive or non primitive to a wider type (i.e. one that can hold more bytes).
Example:
short -> int
String -> Object
But, int -> Integer
is not widening; it's boxing. Widening has a higher priority than boxing. Also both widening and boxing can't be done together, i.e.
int -> Long // cannot be done - both widening and boxing
int -> long // can be done - only widening
I think the order is pretty fascinating. I made out the following playground to see every possible combination. This are my functions:
static void doSomeThing(short i) {
System.out.println("short");
}
static void doSomeThing(short... i) {
System.out.println("short...");
}
static void doSomeThing(Short i) {
System.out.println("SHORT");
}
static void doSomeThing(Short... i) {
System.out.println("SHORT...");
}
static void doSomeThing(long i) {
System.out.println("long");
}
static void doSomeThing(long... i) {
System.out.println("long...");
}
static void doSomeThing(Long i) {
System.out.println("LONG");
}
static void doSomeThing(Long... i) {
System.out.println("LONG...");
}
static void doSomeThing(int i) {
System.out.println("int");
}
static void doSomeThing(int... i) {
System.out.println("int...");
}
static void doSomeThing(Integer i) {
System.out.println("INTEGER");
}
static void doSomeThing(Integer... i) {
System.out.println("INTEGER...");
}
static void doSomeThing(Object i) {
System.out.println("Object");
}
static void doSomeThing(Object... i) {
System.out.println("Object...");
}
Rules:
1.Searches for exactly the same type (int -> int)
2.Widening (int -> long)
3.Boxing (int-> Integer, it is NEVER possible to implicit box AND wide (int -> Long NOT possible without cast))
!!Multiple boxing go BEFORE var args!!
int -> Object will be chosen before int -> int...
4.Var args (int -> int...)
5.Widening + var args (int -> long...)
6.Boxing + var args (int -> Integer...)
7.Boxing + widening + var args (int -> Object...)
public class Main{
public static void main(String...args) {
//primitive int
int i = 0;
doSomeThing(i); //int
//commented out doSomeThing(int i){}
doSomeThing(i); //long. It is not possible to narrow, so short, short... Short and Short... will NEVER be called when the input is larger than a short.
//commented out doSomeThing(long i){}
doSomeThing(i); //INTEGER
//commented out doSomething(Integer i){}
doSomeThing(i); //Object. Notice that there can be multiple boxing before moving to var args
//Error occured: compiler if confused: can either execute int..., long..., Object... or Integer...
//Object... and Integer... are commented out, because in the real world int... will be called first
doSomeThing(i); //int...
//commented out int...
doSomeThing(i); //long...
//commented out long... and uncommented Integer...
doSomeThing(i); //Integer...
//commented out Integer... and uncommented Object...
doSomeThing(i); //Object...
//Integer
//Integer
Integer i = new Integer(0);
doSomeThing(i); //INTEGER
//commented out doSomeThing(Integer i)
doSomeThing(i); //Object
//commented out doSomeThing(Object i)
doSomeThing(i); //int
//commented out doSomeThing(int i)
doSomeThing(i); //long so NOT int... it goes widening again
//commented out doSomeThing(long i)
//Error occured: compliler refused: not both have int..., long..., Integer... and Object...
//int... and long... are commented out
doSomeThing(i); //INTEGER...
//commented out doSomeThing(Integer... i)
doSomeThing(i); //Object...
//commented out doSomeThing(Object... i)
//uncommented doSomeThing(int... and long...)
doSomeThing(i); //int...
//uncommented doSomeThing(int... i)
doSomeThing(i); //long...
}
© 2022 - 2024 — McMap. All rights reserved.