How is multimethod selection being used in this java example? [duplicate] - java

Besides that Java inheritance is a fundamental feature of the language, I have some questions.
Here is the source for my testing example:
class MyClass{
public void say(String t){
System.out.println("Hello MyClass "+t);
}
public void print(MyClass t){
System.out.println("MyClass is printed");
}
public void anotherPrint(int i){
System.out.println("MyClass is printed again");
}
}
class MyClass2 extends MyClass{
public void say(String t){
System.out.println("Hello MyClass2 "+t);
}
public void print(MyClass2 t){
System.out.println("MyClass2 is printed");
}
public void anotherPrint(double i){
System.out.println("MyClass2 is printed again");
}
}
public class HelloWorld{
public static void main(String []args){
MyClass klass = new MyClass2();
klass.say("h"); //Question 1 (Prints: "Hello MyClass2 h")
klass.print(new MyClass2()); //Question 2 (Prints: "MyClass is printed")
klass.print(new MyClass()); //Question 3 (Prints: "MyClass is printed")
klass.anotherPrint(1); //Question 4 (Prints: "MyClass is printed again")
klass.anotherPrint(1.0); //Question 5 (Throws Exception!)
}
}
I have the following questions:
1. The klass object is instance of MyClass. Why does it execute the method from the MyClass2 class?
2,3 . At question 1 klass calls the method of the MyClass2 class. Here I used a parameter that fits to each one of the overridden and overloaded (simultaneously) methods. Why klass object always calls the method from the MyClass class?
4. It is normal. No question at all.
5. It is right to throw an exception. The klass object does not have this method with double parameter. But, why it is not called the method from the MyClass2 class, just like it happened at Question 1?

1. The klass object is instance of MyClass.
No it is a reference variable of type MyClass but referring to an object of MyClass2.
2. Why does it execute the method from the MyClass2 class?
Since you are invoking say() on an object of MyClass2, it executes the say() of MyClass2. Expected behavior.
This is called the run time polymorphism in Java. This provides the ability to override functionality already available in the class hierarchy tree. At run time, which version of the method will be invoked is based on the type of actual object stored in that reference variable and not on the type of the reference variable.
3. At question 1 klass calls the method of the Class2 class. Here I used a parameter that fits to each one of the overridden and overloaded (simultaneously) methods. Why klass object always calls the method from the MyClass class?
That is not overridden method. 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.An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type.Your method signatures are different. Hence invoking klass.print() where klass is a MyClass reference will always refer to the print() of MyClass.
4. It is right to throw an exception. The klass object does not have this method with double parameter. But, why it is not called the method from the MyClass2 class, just like it happened at Question 1?
Because at compile time, the compiler validates if you can call a method based on the reference type. Here the reference type is MyClass and since MyClass doesn't define anotherPrint(double), the compiler complains.It is a compile time check.In question 1, compiler verified klass.say("hi") and it saw that there exists a method in MyClass which can be invoked this way. At that time, it was not concerned whether klass reference variable will refer to a MyClass object or MyClass2 object at runtime. Hence it worked.
You can refer to these Oracle's tutorials here.

An instance of a class will have the methods of the father(s) plus its own methods. If the signature of one of the child class is the same than the signature of a method in the father, will override it.
In this example, an instance of MyClass2 will have this methods:
public void say(String t) //From MyClass2 (override)
public void print(MyClass2 t)
public void anotherPrint(double i)
public void print(MyClass t) //Inherited from MyClass
public void anotherPrint(int i) //Inherited from MyClass
But you are declaring klass as a MyClass, so it will have available this methods
public void say(String t) //From MyClass
public void print(MyClass t)
public void anotherPrint(int i)
Now, answering your questions
1 - You invoke the method say of a MyClass. But in runtime, actually klass is an object of MyClass2 and MyClass2 overrides this method, so it will invoke the one from MyClass2
2,3 - You invoke the method print of MyClass. In runtime, klass is from MyClass2, but MyClass2 IS NOT OVERRIDING THIS METHOD. The signature is different. So the one to be called is the MyClass. Works fine with a MyClass2 object as parameter since MyClass2 is a MyClass
5 - MyClass has not any method called anotherPrint receiving a double

Question 1:- With the line MyClass klass = new MyClass2(); you have done upcasting, catching the reference id(object) of child class. In case of upcasting, the methods of the child class are called.
Though the compiler checks for the say() function in the parent at comiple time but at run time compiler sees that we have say() function in child also, so it binds it with the child class method and calls it. This is the reason you are getting the output for Question 1 as Hello MyClass2 h

Method overloading and method overriding in Java is two important concept in Java which allows Java programmer to declare method with same name but different behavior. Method overloading and method overriding is based on polymorphism in Java. In case of method overloading, method with same name co-exists in same class but they must have different method signature, while in case of method overriding, method with same name is declared in derived class or sub class.Method overloading is resolved using static binding in Java at compile time while method overriding is resolved using dynamic binding in Java at runtime. In short When you overload a method in Java its method signature got changed while in case of overriding method signature remains same but a method can only be overridden in sub class. Since Java supports polymorphism and resolve object at run-time it is capable to call overridden method in Java
Read more: http://javarevisited.blogspot.com/2011/12/method-overloading-vs-method-overriding.html#ixzz34EEhLp2u

Related

why is 'this' keyword returning address of class B?

When I call the super class method ma() it is printing the address of B.My question is in this program what is the function of this keyword. Why using this keyword inside print statement not giving syntax error rather it gives error for the super keyword.why it will print reference of B only why not A class.
class A
{
public void ma()
{
System.out.print(this); //printing address of B why?
}
}
class B extends A
{
public void mb()
{
super.ma(); //calling super class method
}
public static void main(String[] args)
{
A re=new B(); //creating object for class B
re.mb(); //calling method mb() of class B
}
}
this is a reference to the current object — the object whose method or constructor is being called
ma() method of class A is indirectly invoked using instance of class B.
A re=new B(); //creating object for class B
re.mb();
this always refer to the object on which the method is called. Always.
Look closely at your code, have you ever created a new instance of A? No. Then no identifier can refer to an A object, so logically your code can never output the address of an A object.
I think you misunderstood the meaning of super. It just means "to call the super class implementation of this method", not "call this method by creating an instance of the super class". Therefore, super will only make a difference if your derived class has a different implementation of the method. Here, it doesn't.
Even though you are calling the super implementation, the object on which you call this method does not change. It is still this.

Java - inheritance and type of variables when invoking a method

I have some big issue understanding the result of some code.
public class ClassA {
public void stampa(ClassA p) {
System.out.println("AAA");
}
}
public class ClassB extends ClassA {
public void stampa(ClassB p) {
System.out.println("BBB");
}
public void stampa(ClassA p) {
System.out.println("AAA/BBB");
}
}
public class ClassC extends ClassA {
public void stampa(ClassC p) {
System.out.println("CCC");
}
public void stampa(ClassA p) {
System.out.println("AAA/CCC");
}
}
And the main that looks like this
public static void main(String[] args) {
ClassA a1, a2;
ClassB b1;
ClassC c1;
a1 = new ClassB();
b1 = new ClassB();
c1 = new ClassC();
a2 = new ClassC();
b1.stampa(b1);//BBB
a1.stampa(b1);//AAA/BBB
b1.stampa(c1);//AAA/BBB
c1.stampa(c1);//CCC
c1.stampa(a1);//AAA/CCC
a2.stampa(c1);//AAA/CCC
}
I'm having a hard time understanding why the result for a1.stampa(b1); is "AAA/BBB" and not "BBB".
As i did understand from inheritance the static type of a1 in compile time is ClassB so i searche for the "stampa" method in ClassB, and for the parameter of the method, the static type is ClassB also, so I will choose the first stampa method of the ClassB.
The same thing also happens when i try to understand the result of a2.stampa(c1); which is "AAA/CCC" and not "CCC".
Can someone please help me to understand what i'm doing wrong?
The issue is that the following
public class ClassB extends ClassA {
public void stampa(ClassB p) {
is not overriding this
public class ClassA {
public void stampa(ClassA p) {
It is overloading it instead...
This means it is an extra method, rather than an override and it can only be accessed via b1.stampa(b1);.
Overrides only happens if you have the same method signature, with the exception of something called 'co-variant returns', essentially the same concept, but return type is a subclass.
This is a problem related to overloaded and polymorphism.
ClassA a1;
ClassB b1;
...
a1.stampa(b1);
The compiler can only determine the two parameters type and the function name be invoked when compile(because of polymorphism).
so "a1.stampa(b1);" make compile find stampa with parameter type ClassB in ClassA, but ClassA don't hava this function, so parameter be demoted, compile find stampa with parameter type ClassA in ClassA. This function is exist, so compiler record in this line that a function with name stampa and parameter type ClassA should be invoke in here.
When program running, a1 is actually a ClassB object, this object overwrite the function with name stampa and parameter type ClassA. Therefore, the final output is "AAA/BBB".
Just remember overload occurs at compile time, and polymorphism occurs at execute time.
Please ignore my broken English.
It is about the difference between overriding and overloading of methods.
Methods have a signature, defined by the method name and the parameter types, but not the parameter names or the return type.
You can define multiple methods on a class with the same name, as long as the signatures are different. This is called overloading.
If a subclass defines a method with the same signature as the superclass, the subclass is overriding the superclass method. This means that the subclass method will be called, regardless of the type of the variable used to make the call.
The Java compiler determines which method to call at compile-time, i.e. the method signature to use. The actual method with that signature to be called is determined at run-time, depending on the actual class of the referenced object.
So, at compile-time, for a1.stampa(b1) the compiler looks at all the stampa on class ClassA (because a1 is of type ClassA), and only finds one such method, with signature stampa(ClassA).
At run-time, the object referenced by a1 is actually a ClassB, so the ClassB.stampa(ClassA) is called, since ClassB had overridden the method from ClassA.
ClassB.stampa(ClassA) then prints AAA/BBB.
According to my knowledge the result for a1.stampa(b1); is "AAA/BBB" and not "BBB" because when you are passing b1 to stampa() it will be type casted to superclass reference and because you have overloaded method of superclass and while execution of overloaded methods always subclass methods gets preference so subclass method is executed instead of superclass.
This is Runtime Polymorphism which is achieved by the overridden methods.
First of all ,you cannot even expect a1.stampa(b1); to call a method which is not overriding the parent class method (which in your case happens to be public void stampa(ClassB) ) .This method will never get called from your call as it is not overriding the parent class method.
Now the reason why the public void stampa(ClassA p) gets called is because at runtime the parent class reference variable a1 refers to the object of ClassB.So,the method which overrides the parent class method is called.
The same is the case with your other problem.
For better understanding of Runtime polymorphism you can refer to https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html

why does the default constructor in MyClass calls super i.e of Object class

I've been working with java and learning i've a question regarding default constructor in a class. Why does it call super (constructor of Object class.I know it does constructor chaining)?. For what reasons it is required ?. If I define a class like this
MyClass
{
public MyClass()
{
}
}
the compiler adds super in the constructor.
public MyClass()
{
super();
}
P.S I've tried googling and have read Oracle Doc but couldnt find the answer .why?
Thanks for your time.
Every constructor must call either a different constructor of the same class or a constructor of its direct super class. The call to the super class constructor is added implicitly if you don't call it explicitly.
Since an instance of a class inherits the state of its ancestors, it must initialize it by calling the constructors of its ancestors.
In your case, your MyClass is a direct sub-class of Object, so your constructor must call the constructor of Object.
A class always is a chain of classes, and always ending with Object (where Object is the only exception; it has no super class).
If a new instance is created, than all the classes in the chain must be initialized, otherwise their state would be undefined. This also applies to classes that seem not to need initialization (like Object).
Initialization is done partially implicitly (variables getting their default values) and for the other part by always calling a constructor in the class.
Why does it call super (constructor of Object class.I know it does
constructor chaining)?. For what reasons it is required ?
Consider this example:
class A {
protected String s;
A () {
this.s = "hello";
}
}
class B extends A {
public String get() {
return s;// s is inherited from A
}
}
// A's default constructor is invoked here
System.out.println(new B().get());// prints hello
Lets say for now java does not include the super() in the constructor.
// A's default constructor is not invoked here
System.out.println(new B().get());// prints null
It gives null as the default value for class types. Since A's constructor is not invoked for new instance of B the instance variable of A is not initialized.

Invoke a method of a class which is implemented in her supperclass

I have a class java ProductManager which extends another class with the same name,
located in another project with another package("com.services") .
I have to invoke a method deleteProduct(Long productId) located in the super-class.
try{
Object service = CONTEXT.getBean("ProductManager");
Method method = service.getClass().getDeclaredMethod("deleteProduct", Long.class);
method.invoke(service, productId);
} catch(Exception e){
log.info(e.getMessage());
}
I couldn't delete the product:
I get this info:
com.franceFactory.services.ProductManager.deleteProduct(java.lang.Long)
the product isn't deleted :(
The various getDeclaredMethod() and getDeclaredMethods() only return methods declared on the current class instance. From the javadoc:
This includes public, protected, default (package) access, and private methods, but excludes inherited methods.
The important part here is "but excludes inherited methods". This is why you are getting an exception with your code as it currently stands, it is not returning the deleteProduct() method from the parent class.
Instead if you wanted to continue using reflection you would need to use the getMethod method as this returns all public methods, "including those declared by the class or interface and those inherited from superclasses and superinterfaces."
If you have to use reflection then don't use getDeclaredMethod() because (as its name suggest) it can return only methods declared in current class, while you claim you want to invoke method declared in other class (to be precise declared in super class).
To get public method (including also inherited ones) use getMethod().
If your are overriding that method, just use the reserved word super (from the Oracle documents):
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod(); // This calls to the method defined in the superclass
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
This code will write:
Printed in Superclass.
Printed in Subclass
In other case (you are not overriding it, just using it), just write this.methodName(...). All methods inherited are directly available.
Disclaimer: I am not sure I totally understand your question. I will still try to answer what I think I understand.
The Product in package com.franceFactory.services (Lets call it A)
extends The Product class in package com.services (Lets call it B)
So A extends B.
B has method deleteProduct(java.lang.Long)
A overrides the method deleteProduct(java.lang.Long)
You have instance of Class A. So by OOPS concept method deleteProduct of object A is going to get called.
There is no way you can call the super method from outside unless you have the instance of class B.
EDIT
OPs Clarification yes, it's public, but it isn't overridden in my class
The method in super is getting called here. The product is not getting deleted for reason on what is written on the method.

Inheriting static methods in Java?

So I know that in Java when you have a static method you are supposed to call it with the format ClassName.method() rather than use the same structure as you would for instance methods, namely:
ClassName myObject = new ClassName();
myObject.method();
However, if you were to do it this way it would still be valid code and would work. Let's say I decide to do this where the method in question is static, and have the following setup:
public SuperClass {
public static int foo(int x) {
return x;
}
}
public SubClass extends SuperClass {
public static int foo(int x) { // Overriding foo() in SuperClass
return x + 1;
}
}
public MyDriver {
public static void main(String[] args) {
SuperClass myObject = new SubClass(); // Upcasting.
System.out.println(myObject.foo(5)); // This should polymorphically print 6
}
}
What prints out on the screen, however, is 5 rather than 6. Why?
Static methods apply only to the class they are defined in, and they cannot be overridden.
When you call myObject.foo(5), you are calling SuperClass.foo(5) in reality, because you declared myObject as a SuperClass, regardless of whether you instantiated it as one.
The proper way to call a static method is to call it directly from the class it is declared in, so if you wanted to call SubClass.foo(), you must call it from an explicitly declared SubClass instance (meaning no upcasting), or you need to call SubClass.foo() like so.
The simple answer is that calling static methods from instances evaluates to calling those same methods from the declared type with no instance rather than the instance type.
I am not certain of this, but I would not be surprised if when the code is compiled into byte-code, that the instance static method call would actually be compiled into a direct call to the declared type.
Edit: An upvote brought my attention back to this and I cleaned up the explanation to make it more clear and fix some negligible grammatical mistakes on my part. I hope this helps future readers.
Using instances of a class to call that class's static methods is something you should avoid, since it can cause confusion. If you need to call any method polymorphically, make it an instance method. You cannot polymorphically call a static method. The reason the SuperClass invocation is called is because that is the apparent class of myObject at compile-time. This effect can also be seen in the following scenario:
public void doSomething(SuperClass param) {
System.out.println("SuperClass");
}
public void doSomething(SubClass param) {
System.out.println("SubClass");
}
public void test() {
SuperClass myObject = new SubClass();
doSomething(myObject);
}
If test() is called, SuperClass will be printed.
Static methods don't depends on the instance, they belong to the class and only to the class, in fact if you have a static method you'll always access to one unique instance always.
myObject.foo(5)
is only a shortcut, what you really are doing is
SuperClass.foo(5)
Static methods are treated as global by the JVM, they are not bound to an object instance at all. By the way, you can only overload static methods, but you can not override. So check for "Oracle Documentation for Overriding and Hiding Documents".
Defining a Method with the Same Signature as a Superclass's Method:
-----------------------------------------Superclass Instance MethodSuperclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides

Categories