I have two classes:
public class ClassA {
public void method(Number n) {
System.out.println(\"ClassA: \" + n + \" \" + n.getClass());
}
}
because number 3 is automatically boxed to Integer.
please see the link below: http://www.javabeat.net/articles/print.php?article_id=31
General Rule: Arguments are implicitly widened to match method parameters. It's not legal to widen from one wrapper class to another.
In overloading, method resolution always takes care by compiler based on reference type. So, In overloading runtime object[new ClassB()] does not play any role. Therefore, in your case the method of ClassA was executed.
ClassA a = new ClassB();
a.method(3);
Your issue stems from the fact that (as quoted from the official Java tutorials on Inheritance):
In a subclass, you can overload the methods inherited from the superclass. Such overloaded methods neither hide nor override the superclass methods—they are new methods, unique to the subclass.`
Refer to the official Java tutorials for more details: http://docs.oracle.com/javase/tutorial/java/IandI/override.html
Since the two operations have different argument (parameter) types (Even though they are subclasses) they are considered different (Unlike C) you did not override the first method with the second one. Instead you ended up with class B which now has two methods
public void method(Number n) and
public void method(Integer n)
by default when you did a.method(3) 3 was casted to an Integer object. You can verify this by calling
a.method((Number)3); //this would call the second method/operation.
You can also verify this by using reflection to iterate on class B's methods.
I did some R&D on this problem and come up with solution to remove your confusion. Hopefully it will help you to understand.
Look for some below code:
class A {
public void func(Number obj){
System.out.println("In a func");
}
public void func(Integer obj){
System.out.println("In b func");
}
}
class B extends A {
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
If you will run this code you will get output:
"In b func"
"In b func".
In this case, here are 4 methods:
Now when you call b.func(3) on reference of B, it will see the "method 3" and "method 4", which have parameter with most fit derived class. Here both Number and Integer classes are fit for argument 3, but Integer is derived from Number, so func(Integer)[method 3] will be called. Hence the output is "In b func"
Second output is also "In b method", because of same logic. First remember, you can not call any method on class A reference which class A is not having. So you can only call those methods on reference of class A which it have. No matter the instance is of class A or it's subclass's instance.
You need to understand it in 2 terms, compilation and linking and execution.
Now Class A is having both the methods, so when compiler look a.func(3) on reference of class A. Compiler will look into "methods 1" and "method 2" of class A and bind the method signature which have arguments with most fit derived class. So is "func(Integer)".
Now at run time, func(Integer) will be executed, it is called of class B, because instance is of class B. (At runtime, method is executed from the class, whose instance is calling the method). So method 4 is called. Hence the output.
I am sure, you will have confusion, why method 2 is not called and method 4 is called.
If you will run below code:
class A {
public void func(Number obj){
System.out.println("In a func");
}
public void func(Integer obj){
System.out.println("In b func");
}
}
class B extends A {
public void func(Number obj){
System.out.println("In a func of class B");
}
public void func(Integer obj){
System.out.println("In b func of class B");
}
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
Output will be:
In b func of class B
In b func of class B
Now you can understand this code with above explanation. Either we have called fun(3) on reference of class A or class B. Each time class B's method is called (method 4). Because the instance is of class B. But if class A will not have (method 2). Method 4 will not be called on "a.func(3)"
Lets have a look on below code:
class A {
public void func(Number obj){
System.out.println("In a func");
}
}
class B extends A {
public void func(Integer obj){
System.out.println("In b func");
}
}
public class X {
public static void main(String s[]){
B b = new B();
b.func(3);
A a = new B();
a.func(3);
}
}
Output of this program is:
In b func
In a func
Now you may have confusion why is it different output?
Remember, here are not 4 methods. Here are only 3 methods:
Now if you call a.fun(3), class A is not having func(Integer), and you can not call method on reference of class A which class not have. So compiler will not bind func(Integer) because there is no such method in class A. But there is another method func(Number) which can be called with the same code a.func(3) Autoboxing concept of java.
So when a.func(3) called, it basically call func(Number). Now because the instance is of class B, method func(Number) of class B is called. Hence the output is "In a func"
This is a very big answer, but I explained in deep, so you can easily understand different possibilities of outputs in different usecases.
Enjoy coding!