Difference between revisions of "Autoboxing"
From Suhrid.net Wiki
Jump to navigationJump to search(35 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | == | + | == Wrapper Classes == |
* Wrapper classes for primtives are a mechanism to include primitives in activities reserved for objects. e.g. being part of Collections. | * Wrapper classes for primtives are a mechanism to include primitives in activities reserved for objects. e.g. being part of Collections. | ||
* Wrapper objects are '''immutable''' ! | * Wrapper objects are '''immutable''' ! | ||
+ | * All have two constructors - one takes a primitive, other a string representation. | ||
+ | * '''Static''' convenience methods: | ||
+ | ** valueOf() method also takes a string and returns a wrapper object in return. Also accepts an optional base (for Octal, Hex etc) | ||
+ | ** String to primitive - e.g. Integer.parseInt("22"), Double.parseDouble("3.14"); Note: the parseXXX methods throw a runtime NumberFormatException if the string cannot be parsed. | ||
+ | ** Base conversion is possible through static utility methods in Integer and Long - e.g. toBinaryString(), toHexString() and toOctalString(). | ||
+ | * '''Instance''' method: | ||
+ | ** Wrapper to primitive - use the xxxValue() methods like intValue() and floatValue() | ||
+ | ** toString() returns the string representation of the value represented by the wrapper. | ||
+ | * Boolean wrapper takes a String argument (through constructor or valueOf method). If String is equivalent to "true/TRUE/True" etc- case INsensitive, then the Boolean value represents true, else it represents false (for all other string values '''INCLUDING NULL''') | ||
+ | == Autoboxing Intro == | ||
+ | * New feature in Java 5 which avoids having to manually wrap and unwrap a primitive. | ||
+ | * Almost everywhere, the wrapper and the primitive are interchangeable and the wrapper can be used like a primitive. | ||
+ | * But since wrappers are immutable, any "change" in the wrappers value leads to a new wrapper object being created. See below: incrementing y means y will refer to a new object. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Integer y = new Integer(42); | ||
+ | Integer x = y; | ||
+ | System.out.println(x==y); //Prints true | ||
+ | y++; | ||
+ | System.out.println(x==y); //Prints false | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Equality == | ||
+ | |||
+ | * Primitives and Wrappers can be compared for equality using the '==' operator. The wrapper will be automatically unboxed. | ||
+ | * Wrapper's equals() method will check if the values are the same. | ||
+ | * Like the string pool, JVM tries to save memory when wrappers are used, so a pool is maintained for certain values of wrappers. | ||
+ | * '''The '==' operator will return true when for wrapper references when their values are the same and they:''' | ||
+ | ** All Boolean Wrappers | ||
+ | ** All Byte Wrappers | ||
+ | ** Character from \u0000 to \u007f | ||
+ | ** Short and Integer from -128 to 127 | ||
+ | * Note, these are for '''literal values only.''' Any Wrapper created using the new operator will always be a separate object. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | public class Equality { | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | |||
+ | Integer i1 = 64; | ||
+ | Integer i2 = 64; | ||
+ | |||
+ | System.out.println(i1 == i2); //True | ||
+ | |||
+ | Integer i3 = new Integer(111); | ||
+ | Integer i4 = new Integer(111); | ||
+ | |||
+ | System.out.println(i3 == i4); //False | ||
+ | |||
+ | Character c1 = '\u0000'; | ||
+ | Character c2 = '\u0000'; | ||
+ | |||
+ | System.out.println(c1 == c2); //True | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Assignments == | ||
+ | |||
+ | * Note since Wrappers are not compatible types, assignments to wrappers is tricky. | ||
+ | * For Wrappers smallers than "Int", the compiler automatically puts in a cast (like it does for primitives) | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Short s = 5; //OK compiler adds an implicit cast for 5 to short which is then wrapped to Short | ||
+ | |||
+ | Int i = 10; //OK - Standard boxing | ||
+ | |||
+ | Long l = 20; //NOT OK - Compiler does not add a cast, an int is NOT-A Long so this fails. | ||
+ | |||
+ | Long l = 20l; //Make it explicitly long - Now OK | ||
+ | |||
+ | Float f = 1.3; //NOT OK - 1.3 is double by default | ||
+ | |||
+ | Float f = 1.3f; //Now OK | ||
+ | |||
+ | Double d = 4.5; //OK - 4.5 is double by default. | ||
+ | |||
+ | short s2 = 11; | ||
+ | |||
+ | Integer iref = s2; //NOT OK. a Short is NOT-A Integer | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | * Similar to primitives, any two operations involving int literals is an int | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Byte b1 = 10; | ||
+ | Byte b2 = 20; | ||
+ | |||
+ | Byte c3 = b1 + b2 ; //NOT OK | ||
+ | |||
+ | Byte c3 = (byte) b1 + b2; //OK - note cast is for byte and not Byte. | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * Compound assignment operators are not allowed on Wrappers smaller than Integer | ||
+ | * Because the result of the operation in an integer which cannot be cast to the Wrapper Type. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Short s1 = 10; | ||
+ | |||
+ | s1 *= 10; //Wont work | ||
+ | |||
+ | s1 = (short) (s1 * 10); //This is OK | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * Assigning Wrappers to primitives | ||
+ | |||
+ | * For the same type unboxing will happen. | ||
+ | * For narrower types casting needs to be added. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Integer iref = 10; | ||
+ | |||
+ | short s = (short) iref.intValue(); | ||
+ | |||
+ | Byte bo = 20; | ||
+ | |||
+ | long lp = bo; //OK - bo is unboxed to a byte which can be widened to a long | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Overloading == | ||
+ | |||
+ | * In every case when an exact match isnt found - the JVM uses the method with the smallest argument that is wider than the parameter. | ||
+ | |||
+ | |||
+ | * '''Widening is preferred over Boxing'''. This is to allow legacy code to function the way it used to. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | public class OverloadTest { | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | int i = 42; | ||
+ | foo(i); | ||
+ | } | ||
+ | |||
+ | static void foo(Integer x) { | ||
+ | System.out.println("Box"); | ||
+ | } | ||
+ | |||
+ | static void foo(float f) { | ||
+ | System.out.println("Widen"); //Widen will print. | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * '''Widening is prefered over Var-Args'''. Again, this is to preserve legacy code behavior because var-args is a Java 5 feature. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | static void foo() { | ||
+ | byte a = 10; | ||
+ | byte b = 20; | ||
+ | go(a, b); | ||
+ | } | ||
+ | |||
+ | |||
+ | static void go(byte... x) { | ||
+ | System.out.println("Var Args"); | ||
+ | } | ||
+ | |||
+ | static void go(long x, long y) { | ||
+ | System.out.println("Widen"); //Widen will print. | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * Finally, '''Boxing beats Var-args'''. This is because var-args is more broader than boxing, since the varargs can accept any number of arguments. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | int a = 10; | ||
+ | int b = 20; | ||
+ | foo(a, b); | ||
+ | } | ||
+ | |||
+ | static void foo(Integer x, Integer y) { | ||
+ | System.out.println("Boxing"); //Will print Boxing | ||
+ | } | ||
+ | |||
+ | static void foo(long ... la) { | ||
+ | System.out.println("Var-Args"); | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | * '''Illegal to widen wrapper classes''' ! Because Integer is NOT A Long and a Short is NOT A Integer. | ||
+ | * An int can be boxed to an Integer, it can fit into a long, but cannot be matched to a Long. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | int i = 10; | ||
+ | bar(i); //Compiler Error | ||
+ | } | ||
+ | |||
+ | static void bar(Long x) { | ||
+ | System.out.println("Widen"); | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * However this will work because an int can be boxed to an Integer which IS-A Object. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | byte b = 10; | ||
+ | bar(i); //Compiler Error | ||
+ | } | ||
+ | |||
+ | static void bar(Object x) { | ||
+ | System.out.println("Box-and-Widen"); //Will print "Box-and-Widen". | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * '''Note it is OK''' to assign int literals within permissible range to Wrapper types. The compiler adds in a cast automatically (like how it does for primitive types) | ||
+ | * '''However, for a widening assignment''' for e.g. an int assigned to a Long, since an int is NOT a Long, the compiler does not add a cast automatically and this will result in a compile ERROR. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Byte b = 100; //OK | ||
+ | Short s = 500; //OK | ||
+ | |||
+ | Long l = 10; // ERROR. | ||
+ | |||
+ | Long l = 10L; //FIXED | ||
+ | //OR | ||
+ | |||
+ | Long l = (long) 10; //Add a cast | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | * Widening and Boxing can be combined with var-args. This is NOT overloading though. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | static void go() { | ||
+ | int i = 10, j = 20; | ||
+ | foo(i, j) //OK | ||
+ | bar(i, j) //OK | ||
+ | } | ||
+ | |||
+ | static void foo(long... la) { | ||
+ | } | ||
+ | |||
+ | static void bar(Integer... ia) { | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * '''These wont work:''' | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | void go() { | ||
+ | int(3, 4); //AMBIGUOUS | ||
+ | |||
+ | int[] ia = {3,4}; | ||
+ | foo(ia); //OK | ||
+ | Integer[] IA = {3,4}; | ||
+ | foo(IA); //OK | ||
+ | } | ||
+ | |||
+ | void foo(int... ia) { | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | void foo(Integer... ia) { | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | void go() { | ||
+ | foo(3, 4); //Compiler Error - Amibiguous. | ||
+ | } | ||
+ | |||
+ | void foo(int... la) { | ||
+ | } | ||
+ | |||
+ | void foo(long... la) { | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | |||
+ | void go() { | ||
+ | byte a = 10; | ||
+ | byte b = 20; | ||
+ | foo(a, b); //Compiler Error - Amibiguous. | ||
+ | } | ||
+ | |||
+ | void foo(int... la) { | ||
+ | } | ||
+ | |||
+ | void foo(Byte... la) { | ||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | * '''SUMMARY:''' | ||
+ | |||
+ | (From http://www.coderanch.com/t/417622/java-programmer-SCJP/certification/Golden-Rules-widening-boxing-varargs ) | ||
+ | |||
+ | * Widening > Boxing > Varargs. | ||
+ | * Widening and Boxing (WB) not allowed. (int is NOT-A Long) | ||
+ | * Boxing and Widening (BW) allowed. (int is an Integer IS-A Object) | ||
+ | * Only while overloading, Widening + vararg and Boxing + vararg cannot be used together. Can be used separately, that is if methods have different names as in example above. | ||
+ | * Widening between wrapper classes not allowed | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | Overloaded methods Invoked by saying Called method | ||
+ | doX(Integer i) & doX(long l) doX(5) long (by Rule 1) | ||
+ | doX(int...i) & doX(Integer i) doX(5) Integer (by Rule 1) | ||
+ | doX(Long l) & doX(int...i) doX(5) int...i (Rule 2 & 1) | ||
+ | doX(Long l) & doX(Integer...i) doX(5) Integer...i(R. 2&1) | ||
+ | doX(Object o) & doX(Long l) doX(5) Object o (Rule 2&3) | ||
+ | doX(Object o) & doX(int...i) doX(5) Object o (Rule 3&1) | ||
+ | doX(Object o) & doX(long l) doX(5) long l (Rule 3&1) | ||
+ | doX(long...l) & doX(Integer...i) doX(5) ambiguous (Rule 4) | ||
+ | doX(long...l) & doX(Integer i) doX(5) Integer (Rule 1) | ||
+ | doX(Long l) Integer i; error (Rule 5) | ||
+ | doX(i) | ||
+ | doX(Long l) & doX(long...l) Integer i; long...l(Rule 5 & 1) | ||
+ | doX(i) | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Overriding == | ||
+ | |||
+ | * Autoboxing/Unboxing doesnt work when it comes to overriding methods return types. This is true while extending classes also. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | |||
+ | interface A { | ||
+ | |||
+ | public int foo(); | ||
+ | |||
+ | public Integer bar(); | ||
+ | } | ||
+ | |||
+ | class B implements A { | ||
+ | |||
+ | public Integer foo() { //WONT COMPILE - has to return int | ||
+ | return new Integer(42); | ||
+ | } | ||
+ | |||
+ | public int bar() { //WONT COMPILE - has to return Integer | ||
+ | return 42; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * However, things are OK when it comes to method parameters when extending classes. | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | class A { | ||
+ | |||
+ | public void foo(int i) { | ||
+ | |||
+ | } | ||
+ | |||
+ | public void bar(Integer iref) { | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | class B extends A { | ||
+ | |||
+ | public void foo(Integer iref) { //OK | ||
+ | |||
+ | } | ||
+ | |||
+ | public void bar(int i) { //OK | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | * But '''NOT''' for interfaces ! | ||
+ | |||
+ | <syntaxhighlight lang="java5"> | ||
+ | |||
+ | interface A { | ||
+ | |||
+ | public void foo(int i) ; | ||
+ | |||
+ | public void bar(Integer iref); | ||
+ | } | ||
+ | |||
+ | class B implements A { | ||
+ | |||
+ | public void foo(Integer iref) { | ||
+ | |||
+ | } | ||
+ | |||
+ | public void bar(int i) { | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
[[Category:OCPJP]] | [[Category:OCPJP]] |
Latest revision as of 08:35, 13 September 2011
Wrapper Classes
- Wrapper classes for primtives are a mechanism to include primitives in activities reserved for objects. e.g. being part of Collections.
- Wrapper objects are immutable !
- All have two constructors - one takes a primitive, other a string representation.
- Static convenience methods:
- valueOf() method also takes a string and returns a wrapper object in return. Also accepts an optional base (for Octal, Hex etc)
- String to primitive - e.g. Integer.parseInt("22"), Double.parseDouble("3.14"); Note: the parseXXX methods throw a runtime NumberFormatException if the string cannot be parsed.
- Base conversion is possible through static utility methods in Integer and Long - e.g. toBinaryString(), toHexString() and toOctalString().
- Instance method:
- Wrapper to primitive - use the xxxValue() methods like intValue() and floatValue()
- toString() returns the string representation of the value represented by the wrapper.
- Boolean wrapper takes a String argument (through constructor or valueOf method). If String is equivalent to "true/TRUE/True" etc- case INsensitive, then the Boolean value represents true, else it represents false (for all other string values INCLUDING NULL)
Autoboxing Intro
- New feature in Java 5 which avoids having to manually wrap and unwrap a primitive.
- Almost everywhere, the wrapper and the primitive are interchangeable and the wrapper can be used like a primitive.
- But since wrappers are immutable, any "change" in the wrappers value leads to a new wrapper object being created. See below: incrementing y means y will refer to a new object.
Integer y = new Integer(42);
Integer x = y;
System.out.println(x==y); //Prints true
y++;
System.out.println(x==y); //Prints false
Equality
- Primitives and Wrappers can be compared for equality using the '==' operator. The wrapper will be automatically unboxed.
- Wrapper's equals() method will check if the values are the same.
- Like the string pool, JVM tries to save memory when wrappers are used, so a pool is maintained for certain values of wrappers.
- The '==' operator will return true when for wrapper references when their values are the same and they:
- All Boolean Wrappers
- All Byte Wrappers
- Character from \u0000 to \u007f
- Short and Integer from -128 to 127
- Note, these are for literal values only. Any Wrapper created using the new operator will always be a separate object.
public class Equality {
public static void main(String[] args) {
Integer i1 = 64;
Integer i2 = 64;
System.out.println(i1 == i2); //True
Integer i3 = new Integer(111);
Integer i4 = new Integer(111);
System.out.println(i3 == i4); //False
Character c1 = '\u0000';
Character c2 = '\u0000';
System.out.println(c1 == c2); //True
}
}
Assignments
- Note since Wrappers are not compatible types, assignments to wrappers is tricky.
- For Wrappers smallers than "Int", the compiler automatically puts in a cast (like it does for primitives)
Short s = 5; //OK compiler adds an implicit cast for 5 to short which is then wrapped to Short
Int i = 10; //OK - Standard boxing
Long l = 20; //NOT OK - Compiler does not add a cast, an int is NOT-A Long so this fails.
Long l = 20l; //Make it explicitly long - Now OK
Float f = 1.3; //NOT OK - 1.3 is double by default
Float f = 1.3f; //Now OK
Double d = 4.5; //OK - 4.5 is double by default.
short s2 = 11;
Integer iref = s2; //NOT OK. a Short is NOT-A Integer
- Similar to primitives, any two operations involving int literals is an int
Byte b1 = 10;
Byte b2 = 20;
Byte c3 = b1 + b2 ; //NOT OK
Byte c3 = (byte) b1 + b2; //OK - note cast is for byte and not Byte.
- Compound assignment operators are not allowed on Wrappers smaller than Integer
- Because the result of the operation in an integer which cannot be cast to the Wrapper Type.
Short s1 = 10;
s1 *= 10; //Wont work
s1 = (short) (s1 * 10); //This is OK
- Assigning Wrappers to primitives
- For the same type unboxing will happen.
- For narrower types casting needs to be added.
Integer iref = 10;
short s = (short) iref.intValue();
Byte bo = 20;
long lp = bo; //OK - bo is unboxed to a byte which can be widened to a long
Overloading
- In every case when an exact match isnt found - the JVM uses the method with the smallest argument that is wider than the parameter.
- Widening is preferred over Boxing. This is to allow legacy code to function the way it used to.
public class OverloadTest {
public static void main(String[] args) {
int i = 42;
foo(i);
}
static void foo(Integer x) {
System.out.println("Box");
}
static void foo(float f) {
System.out.println("Widen"); //Widen will print.
}
}
- Widening is prefered over Var-Args. Again, this is to preserve legacy code behavior because var-args is a Java 5 feature.
static void foo() {
byte a = 10;
byte b = 20;
go(a, b);
}
static void go(byte... x) {
System.out.println("Var Args");
}
static void go(long x, long y) {
System.out.println("Widen"); //Widen will print.
}
- Finally, Boxing beats Var-args. This is because var-args is more broader than boxing, since the varargs can accept any number of arguments.
public static void main(String[] args) {
int a = 10;
int b = 20;
foo(a, b);
}
static void foo(Integer x, Integer y) {
System.out.println("Boxing"); //Will print Boxing
}
static void foo(long ... la) {
System.out.println("Var-Args");
}
- Illegal to widen wrapper classes ! Because Integer is NOT A Long and a Short is NOT A Integer.
- An int can be boxed to an Integer, it can fit into a long, but cannot be matched to a Long.
public static void main(String[] args) {
int i = 10;
bar(i); //Compiler Error
}
static void bar(Long x) {
System.out.println("Widen");
}
- However this will work because an int can be boxed to an Integer which IS-A Object.
public static void main(String[] args) {
byte b = 10;
bar(i); //Compiler Error
}
static void bar(Object x) {
System.out.println("Box-and-Widen"); //Will print "Box-and-Widen".
}
- Note it is OK to assign int literals within permissible range to Wrapper types. The compiler adds in a cast automatically (like how it does for primitive types)
- However, for a widening assignment for e.g. an int assigned to a Long, since an int is NOT a Long, the compiler does not add a cast automatically and this will result in a compile ERROR.
Byte b = 100; //OK
Short s = 500; //OK
Long l = 10; // ERROR.
Long l = 10L; //FIXED
//OR
Long l = (long) 10; //Add a cast
- Widening and Boxing can be combined with var-args. This is NOT overloading though.
static void go() {
int i = 10, j = 20;
foo(i, j) //OK
bar(i, j) //OK
}
static void foo(long... la) {
}
static void bar(Integer... ia) {
}
- These wont work:
void go() {
int(3, 4); //AMBIGUOUS
int[] ia = {3,4};
foo(ia); //OK
Integer[] IA = {3,4};
foo(IA); //OK
}
void foo(int... ia) {
}
void foo(Integer... ia) {
}
void go() {
foo(3, 4); //Compiler Error - Amibiguous.
}
void foo(int... la) {
}
void foo(long... la) {
}
void go() {
byte a = 10;
byte b = 20;
foo(a, b); //Compiler Error - Amibiguous.
}
void foo(int... la) {
}
void foo(Byte... la) {
}
- SUMMARY:
- Widening > Boxing > Varargs.
- Widening and Boxing (WB) not allowed. (int is NOT-A Long)
- Boxing and Widening (BW) allowed. (int is an Integer IS-A Object)
- Only while overloading, Widening + vararg and Boxing + vararg cannot be used together. Can be used separately, that is if methods have different names as in example above.
- Widening between wrapper classes not allowed
Overloaded methods Invoked by saying Called method
doX(Integer i) & doX(long l) doX(5) long (by Rule 1)
doX(int...i) & doX(Integer i) doX(5) Integer (by Rule 1)
doX(Long l) & doX(int...i) doX(5) int...i (Rule 2 & 1)
doX(Long l) & doX(Integer...i) doX(5) Integer...i(R. 2&1)
doX(Object o) & doX(Long l) doX(5) Object o (Rule 2&3)
doX(Object o) & doX(int...i) doX(5) Object o (Rule 3&1)
doX(Object o) & doX(long l) doX(5) long l (Rule 3&1)
doX(long...l) & doX(Integer...i) doX(5) ambiguous (Rule 4)
doX(long...l) & doX(Integer i) doX(5) Integer (Rule 1)
doX(Long l) Integer i; error (Rule 5)
doX(i)
doX(Long l) & doX(long...l) Integer i; long...l(Rule 5 & 1)
doX(i)
Overriding
- Autoboxing/Unboxing doesnt work when it comes to overriding methods return types. This is true while extending classes also.
interface A {
public int foo();
public Integer bar();
}
class B implements A {
public Integer foo() { //WONT COMPILE - has to return int
return new Integer(42);
}
public int bar() { //WONT COMPILE - has to return Integer
return 42;
}
}
- However, things are OK when it comes to method parameters when extending classes.
class A {
public void foo(int i) {
}
public void bar(Integer iref) {
}
}
class B extends A {
public void foo(Integer iref) { //OK
}
public void bar(int i) { //OK
}
}
- But NOT for interfaces !
interface A {
public void foo(int i) ;
public void bar(Integer iref);
}
class B implements A {
public void foo(Integer iref) {
}
public void bar(int i) {
}
}