We have a Parent and child class, which has method with the same name but argument are as primitive and wrapper. Could someone please explain the reason whether this would be referred as Method Overriding and Method overloading. Running this program would invoke Parent method - which would be overriding and not overloading, looking for explanations.
class Parent {
public void takeValue(int a) {
System.out.println("take value method from parent is invoked");
}
}
class Child extends Parent {
public void takeValue(Integer a) {
System.out.println("take value method from child is invoked");
}
public static void main(String[] args) {
Parent p = new Child();
p.takeValue(new Integer(51));
}
}
The method is overloaded.
Running this program would invoke Parent method - which would be overriding and not overloading
Yes. You're calling takeValue on a Parent variable, which means that the compiler will look for a signature match on the Parent class. The overload is not even visible here (signatures are matched based on static types, i.e., java finds the method based on the declared data type of the variable on which the method is called, not with the data type of the object assigned to the variable, which would be a runtime thing).
And because public void takeValue(Integer a) is not considered by the compiler when checking the method invocation, p.takeValue(new Integer(51)); is linked to Parent.takeValue(int) by virtue of autoboxing (it would have matched the other method if both of them were visible - or declared in the Parent class in this example).
This is overloading. You have same name but type of input parameters are different.
To confirm that, you will get an error when you try to attach the #Override annotation.
Integer and int are different types.
Related
So I was playing around in Java to understand the concept of polymorphism, and I wrote this:
public class Practice
{
public static void main(String[] args)
{
Parent p = new Child();
p.instanceMethod();
}
}
class Child extends Parent {
public void instanceMethod(){
System.out.println("child's instance method");
staticMethod();
}
public static void staticMethod() {
System.out.println("child's static method");
}
}
class Parent {
public void instanceMethod(){
System.out.println("parent's instance method");
staticMethod();
}
public static void staticMethod() {
System.out.println("parent's static method");
}
}
So the output of this is:
child's instance method
child's static method
Why is the the static method called upon from the child's class and not from it's static type, Parent's class?
Is it because, it is first called by the instance method in child's class, so at that point its type is already fully dynamic, aka child's type?
static methods don't 'do' polymorphism. At all.
non-static (i.e. instance) methods do. The signature of the method is bound entirely statically; the actual prospect of finding which method to actually run in the type hierarchy is done entirely dynamically (late binding).
For static methods, the entire thing is entirely static.
So, let's go through this code:
p.instanceMethod()
The expression p is of type Parent. The compiler looks at the signatures available in Parent and all its supertypes and determines that the full method signature that this invocation of instanceMethod() is attempting to invoke is void instanceMethod(). This call (Parent::instanceMethod()V in bytecode speak) is encoded in the emitted .class file.
At runtime, the system checks the actual runtime type of what the p expression resolves to (which is the new Child() you did earlier), and does dynamic dispatch. The public void instanceMethod() of Child, which clearly overrides the one from Parent, is selected and executed, therefore, "child's instance method" is printed.
staticMethod() in Child
Next, let's look at that staticMethod invoke: at compile time, javac determines that this is clearly a reference to the staticMethod() that's right there, in Child. It encodes, in the bytecode an INVOKESTATIC bytecode to Child::staticMethod()V. Dynamic dispatch is not now or ever applied to static method calls.
At runtime.. that method is called.
Simple as that.
Perhaps you expected that a static method still first checks the call context but that's not how java works.
I have a question about method binding. As you know, binding of private, static and final methods happen at compile-time, while binding of overridden methods happen at runtime.
In the following, we have a method something() in Parent, which is not overridden in the corresponding subclass Child.
class Parent {
void something() {
}
}
class Child extends Parent {
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
p.something(); // still dynamically bound?
}
}
Is the call of p.something() in our main program (although it is not overridden) still dynamically bound?
First of all, the method signature is determined at time of compilation. However, method binding is always done at runtime. The exact rules for the runtime dispatch are defined in JLS §15.12.2.5.
So as you are probably guessing now, the call of p.something(); is still dinamically bounded.
As a sidenote, check out this to clearly understand polymorphism.
I have a code and I am not able to get why the output will be "Radial Tire with long".Can somebody help me to understand this code?
class Tyre {
public void front() throws RuntimeException {
System.out.println("Tire");
}
public void front(long a) {
System.out.println("Radial Tire with long");
}
}
class TestSolution extends Tyre {
public void front() {
System.out.println("Radial Tire");
}
public void front(int a) throws RuntimeException {
System.out.println("Radial Tire with int");
}
public static void main(String... args) {
Tyre t = new TestSolution();
int a = 10;
t.front(a);
}
}
front is not overridden in TestSolution, it is overloaded.
You can regard an overloaded function as a completely different function, like one with a different name.
So t.front(a) will call the one in Tyre, with an a implicitly converted to long.
So if we go with definitions
Overloading means methods with same name but with different number or order of parameters.
Overriding means method with same name with same number of parameters along with rules mentioned here
So in your case front method is overloaded in both the classes Tyre and TestSolution
method front() from Tyre class is overridden in class TestSolution.
no overriding in case of method front(long a) and front(int a).
There's no overriding taking place in your main.
t's static (compile-time) type is Tyre, so, since method overload resolution is determined by the compile-time type of the instance, the only front methods available for the compiler to choose from are those declared in the base class Tyre :
public void front()
public void front(long a)
Only the latter (public void front(long a)) matches the arguments of the call t.front(a), and that method is not overridden by the sub-class. Therefore Radial Tire with long is displayed.
Calling ((TestSolution)t).front(a); would invoke the sub-class's method - public void front(int a).
General rule: if I have a variable of one class I can access only methods and components defined in that class.
The only particular case is:
you have a component or method both in the super class and in the subclass (overriding)
you have a variable of the super class and an object of the subclass (your case)
In these cases you can follow the following rule:
for the components the type of the variable decides which to use
for the methods the type of the object does (late binding)
In your case as stated before the method is not overridden so you can't apply the last rule.
Lets understand the difference between overloading and overriding
Overloading:
The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists
Overriding:
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.
Tyre declared front() method with long as parameter.
TyreSolution declared front() method with int as parameter.
Since the method signature is different, TyreSolution overloads Tyre's front() method
If you change signature of front() in TyreSolution to accept long value as input parameter instead of int, then TyreSolution overrides Tyre's front() method.
e.g. TestSolution class definition of front() method
public void front(long a) throws RuntimeException {
System.out.println("Radial Tire with long in TestSolution");
}
output:
Radial Tire with long in TestSolution
public class Test
{
public Test(Object o) {
System.out.println("object");
}
public Test(int[] o) {
System.out.println("array");
}
public static void main(String[] args) {
new Test(null);
}
}
Output :
array
Can somebody please explain me the reason behind this?
The rule is: the more specific method will be called. In this case, it's the method receiving a int[] which is more specific than the one receiving a java.lang.Object parameter.
Here's a link to Java's official documentation referencing to this case. Take a look at section 15.2.2. Quoting an interesting part (section 15.2.2.5):
If more than one member method is both accessible and applicable to a
method invocation, it is necessary to choose one to provide the
descriptor for the run-time method dispatch. The Java programming
language uses the rule that the most specific method is chosen.
The informal intuition is that one method is more specific than
another if any invocation handled by the first method could be passed
on to the other one without a compile-time type error.
An another one:
It is possible that no method is the most specific, because there are
two or more methods that are maximally specific. In this case:
If all the maximally specific methods have override-equivalent
(§8.4.2) signatures, then: If exactly one of the maximally specific
methods is not declared abstract, it is the most specific method.
Otherwise, if all the maximally specific methods are declared
abstract, and the signatures of all of the maximally specific methods
have the same erasure (§4.6), then the most specific method is chosen
arbitrarily among the subset of the maximally specific methods that
have the most specific return type. However, the most specific method
is considered to throw a checked exception if and only if that
exception or its erasure is declared in the throws clauses of each of
the maximally specific methods. Otherwise, we say that the method
invocation is ambiguous, and a compile-time error occurs.
It's always subclass would be preferred over the parent class. If you want to call Object one you could do the following:
new goFuncTest((Object) null);
As pablo's answer suggests, the most specific / least generic method will be called. Actually, the classlevel in the class hierarchy is checked to decide which method to call. The method with lower class level is called.
If 2 classes are at the same level, then you will get a compile time error stating - ambiguous method call just like in the below case.
public class Sample {
void someMethod(Object o) {
System.out.println("object");
}
void someMethod(String s) {
System.out.println("String");
}
void someMethod(int[] o) {
System.out.println("int[]");
}
public static void main(String[] args) {
new Sample().someMethod(null); // error ambiguous call both array and String are direct children of Object
}
Case -2 : To prove that the method with lower class level will be called.
public class Sample {
void someMethod(Object o) {
System.out.println("object");
}
void someMethod(OutputStream os) {
System.out.println("OutputStream");
}
void someMethod(FileOutputStream fos) {
System.out.println("FileOutputStream");
}
public static void main(String[] args) {
new Sample().someMethod(null);
}
}
O/P :FileOutputStream
Since FileOutputStream is child of OutputStream which is again a child of Object class (FileOutputStream is also a child of both OutputStream and Object classes). So the compiler goes like this Object --> OutputStream --> FileOutputStream while resolving the method call.
Thumb rule is child first in method call. As Object is parent of all and as null can be assigned to any type of object instance variable, it will first match any java type(which of course is child of object) and then super parent i.e. Object.
up gradation of Null to Array is preferred over casting it to Object. Object is top in the hierarchy while Array is closest to Null.
This is like up gradation of byte to int.
I have read in multiple places that final methods are early bound but none offers a satisfactory reason. I doubt how can it be so coz even in a final method called on parent class reference, compiler cannot say whether parent's non final or child's final method is called.
Please advice.
class Parent {
void meth() {
System.out.println("parent");
}
}
class Child extends Parent {
#Override
final void meth() {
// TODO Auto-generated method stub
System.out.println("child");
}
public static void main(String[] args) {
Parent parent = new Parent();
Parent child = new Child();
child.meth();
parent.meth();
}
}
In the above code method meth() called on child(a Parent reference) is a final method but then the JVM should need to use a method look up table at run time as in its the child or parent method being called.
Naturally, early binding can occur only if the reference's static type is a class where the method has the final specifier.
Binding in java happens in two stages. At compile time the type of the reference as known to the compiler is used to bind the method to the highest method up the type hierarchy it can be. E.g. if calling toString() on a Number type variable, then the compiler knows it has to call Number.toString() or a sub-class override rather than Object.toString().
Secondly when invoking the method at runtime, the runtime type of the object is looked at and the most specific method in the type hierarchy is found and invoked. I.e. in the case of Number.toString above, if the object is an Integer it will find Integer.toString and call that.
If the method is final in the type of the reference / variable then this second step can be skipped because we know there can be no sub-class override. This is what Dima Rudnick means by the static type. So again with my example, if Number.toString was final, and the variable was type Number then we don't need to look at the runtime type to know what method we're invoking.
Note: for the purposes of this I'm assuming Object, Number and Integer all have a specific toString method rather than relying on the inherited one.