why base class method is invoked? - java

In the following code:
b.show("str");
//prints: from base
d.show("");
//prints: from str
Could one please explain why it's behaving differently?
I am wondering why Base b = new Sub(), that b.show() from base class would be invoked.
I am merely using DifferentClass, as an reference showing b.show(String) is called under an non-inheritance occasion.
public class TestClass {
public static void main(String[] args) {
Base b = new Sub();
b.show("str");
DifferentClass d = new DifferentClass ();
d.show("");
}
}
class Base {
public void show(Object obj) {
System.out.println("from base");
}
}
class Sub extends Base {
public void show(String str) {
System.out.println("from sub");
}
}
class DifferentClass {
public void show(String str) {
System.out.println("from str");
}
public void show(Object obj) {
System.out.println("from obj");
}
}

Because of the reference type.
Base b = new Sub();
b.show("str");
Sub2 s2 = new Sub2();
s2.show("");
In that code, though b is an instance of Sub, the reference type of the variable is Base. Method overloading is evaluated at compile-time, not run-time. That matters because at compile time, once the new Sub() constructor runs and we assign the variable, the compiler is no longer aware of the concrete class. Only that it's a valid Base.
Why does this matter?
Because when the compiler tries to resolve b.show(String), there is no method on Base (the only type it knows of for sure for b) which takes a String, so it passes the string to the show(Object) method.
Sub does not over-ride the show(String) method (though Sub2 does).
By the way, the #Override annotation will help you with this: When do you use Java's #Override annotation and why?

You're invoking with a string so the method show() overloaded with string is called.
Maybe you did not realize that sub2 does not inherit??...

You declare your variable b to be of type Base, then you invoke show() on it. Since it has a show method which matches the signature, that is the method invoked.
Then you declare your variable s2 to be of type Sub2, and invoke show(String) on it. The runtime invokes that method since it matches.

Related

what's the use of java virtual method invokation?

Say I have the following code
public class A {
public void callme() {
System.out.println("Calling of class A function ");
}
}
public class B extends A {
public void callme() {
System.out.println(" Calling of class B fuction ");
}
public void Hello() {
System.out.println("hello guys");
}
}
and a main() that does the following
public class Main {
public static void main(String [] args){
A a = new B();
B b = new B();
b = (B)a;
a.callme();
b.callme();
a.Hello(); // show error : Hello is undefined for method A
}
}
The book says "you get the behavior associated with the object to which the variable refers at runtime". Ok, I get behavior of B class when a method callme is called, but when I access the method Hello, it shows an error that Hello is undefined for method A. why is that?
Polymorphism doesn't work this way. Since A is parent of B, B can inherit methods of A (like son can inherit properties of father), but its not vice versa because A doesn't know which classes are inheriting it (A does not know who are its children.)
For Example, suppose there is one more class C:
public class C extends A {
public void callme(){
System.out.println(" Calling of class C fuction ");
}
public void Hello(){
System.out.println("hello guys, I am C");
}
}
Now, if you use
a.Hello();
how will a know which child class it should call since it does not methods of its child. only its own abstract method, which it knows child will implement for sure.
a is of type A, even if it is referring to an instance of B.
A doesn't have the Hello method (even an abstract declaration). So your compiler emits the error. Adjusting your code slightly to
public abstract class A {
public abstract void Hello();
/*the rest as before*/
would be a fix. A is then assuming the characteristics of an interface.
public class B extends A {
public void callme(){
System.out.println(" Calling of class B fuction ");
}
public void Hello(){ // hello method is only the part of class B not A.
System.out.println("hello guys");
}
}
In above class hello() method is a part of B only. it not override by the method of A.
now in your main method call
public static void main(String [] args){
A a= new B(); // object of b referred by (a) Reference Variable of A
B b= new B(); // object of b referred by (b) Reference Variable of B
b= (B)a;
a.callme(); //override takes place and method of B's Callme() called
b.callme(); //again override takes place here and method of B's Callme() called
a.Hello();// buttttttt
b.Hello(); // this will compile and executes fine.
}
}
Here you used the reference variable of class A which don't have any method name Hello(). So, Method Resolution will not take place(won't be able to find any method like Hello()).
but if you try to call b.Hello() using the reference variable of B then it will work fine to you.
Now suppose there is another class C which is a sub class of A and contains a Method Name Hello().
public class C extends A {
public void Hello(){ // hello method is only the part of class B not A.
System.out.println("hello guys");
}
}
In main a Statement like this
A a = new C();
and if you try to call a.Hello() then which Hello() method will call. Compiler will get confused.
So, This concept work only when you try to override the method of super class in sub Class.
Is the parent class aware of classes derived from it ?
Casting does not change the actual object type. Only the reference type gets changed.
I highly recommend you my upcasting and downcasting writing from the link

Why it is called runtime polymorphism?

I am extending a class but I am not able to figure out why the JVM decides only at runtime which method to call. I mean when I do A obj=new B();, isn't it obvious that the method in B will be called ?
Maybe it is not obvious for compiler but I want to know the details.
Code is as follows :
class A
{
String getName(String name) {
return "super";
}
}
class B extends A
{
#Override
String getName(String name) {
return "sub";
}
}
public class Overload
{
public static void main(String args[]) {
A obj=new B();
System.out.println(obj.getName(null));
}
}
A compiler can only able to check their types and it's functionality is limited. Hence it cannot actually run and see the program output. That is why it belong to run time.
Compiler check it's type, and runtime bind it's functionality.
You know it holds a reference of B, because the complexity of code here is simple.
What if you had class 'C' also extending from class 'A' and if the responsibility of initializing obj is with some other class or may be some config.
Unlike as in compile-type polymorphism where we as well as the compiler can see the single statement and decide which method can be called.
Lets see this scenario:
public abstract class A {
public abstract void sayHello();
}
public class B extends A{
public void sayHello(){
System.out.println("B says Hello!");
}
}
public class C extends A{
public void sayHello(){
System.out.println("C says Hello!");
}
}
public class FactoryA{
public static A getInstance(String type){
if("B".equals(type)){
return new B();
}
else if("C".equals(type)){
return new C();
}
}
}
Lets say that now you ask the factory to get instance based on the String parameter, like this:
A a = FactoryA.getInstance("B"); // the string can come user-input
a.sayHello();
In this output will be "B says Hello!", because the instance you get from Factory's method is an instance of B, which depends on the String parameter passed to it.
In this case it may not be known at the run time which method will be called (B's sayHello() or C's sayHello()). That's why it is called runtime polymorphism.
Because the decision was taken at runtime.

Java field hiding for attributes

I just started to learn Java, so please bear with me if the answer is somewhat obvious. I did some research but no avail.
From what I understand, attributes are not overriden but only field hidden. To determine whether the attribute in the superclass or the subclass is used, Java will check the type of the reference.
Then I don't under stand the output here:
public class Super {
String str = "I'm super!\n";
public String toString() {
return str;
}
}
public class Sub extends Super {
String str = "I'm sub.\n";
}
public class TestFH {
public static void main(String[] args) {
Sub s1 = new Sub();
System.out.printf(s1.toString());
}
}
It gives me:
I'm super!
I understand that I can achieve what I want easily via method overriding. I'm just curious about what's happenning under the hood.
Thanks in advance.
When you call, s1.toString(), it's finding toString() method defined only in Super class hence using that method as super class methods are available in the sub class. Your super class method toString() is using it's own class variable str (with value initialized in super class) as the return value from the method and hence the behavior i.e. output as I'm super!.
If you want to get the output as I'm sub.\n then you need to reuse the same variable as in the super class and assign the new string value i.e. I'm sub.\n to it. Best option is to use constructors as:
public class Super {
String str = "I'm super!\n";
public Super(String stringValue){
this.str = stringValue;
}
public String toString() {
return str;
}
}
public class Sub extends Super {
public Sub(){
super("I'm sub.\n");
}
}
public class TestFH {
public static void main(String[] args) {
Sub s1 = new Sub();
System.out.printf(s1.toString());
}
}
You're hiding (shadowing) str in your child class. Since you have not overridden toString() in your child class, the call is being made in the parent class, and it sees the parent's str.
If you did this:
public class Sub extends Super {
public Sub() {
this.str = "I'm sub.\n";
}
}
It would output what you're expecting.
This call is using the super class:
Sub s1 = new Sub();
System.out.printf(s1.toString());
The reason is that Sub is not overriding str, it is just declaring another variable that happens to have the same name. In other words, sub is just hiding the variable in Super (data members are not polymorphic).
You could give them different names if they mean different things. Or maybe have the Sub access (or modify) the parent's attribute using a getter method.
you're not assigning the string literal, "I'm sub.\n" to the shared superclass field, you're creating a field local to the subclass and assigning it to that instead.
for example,
public class EncapsulationDemo {
public static void main(String[] args){
MySuperObject obj = new MySubObject();
System.out.println(obj); // prints I'm sub.
}
private static class MySuperObject{
String str = "I'm super."; // protected, can be accessed directly
// by subclasses
#Override
public String toString(){
return str;
}
}
private static class MySubObject extends MySuperObject{
MySubObject(){
super();
str = "I'm sub."; // assign to superclass field
}
}
}
for more information, please see Controlling Access to Members of a Class.

Can a private method in super class be overridden in the sub-class?

Can private methods be overridden in Java?
If no, then how does the following code work?
class Base{
private void func(){
System.out.println("In Base Class func method !!");
};
}
class Derived extends Base{
public void func(){ // Is this a Method Overriding..????
System.out.println("In Derived Class func method");
}
}
class InheritDemo{
public static void main(String [] args){
Derived d = new Derived();
d.func();
}
}
No, you are not overriding it. You can check by trying to mark it with #Override, or by trying to make a call to super.func();. Both won't work; they throw compiler errors.
Furthermore, check this out:
class Base {
private void func(){
System.out.println("In base func method");
};
public void func2() {
System.out.println("func2");
func();
}
}
class Derived extends Base {
public void func(){ // Is this an overriding method?
System.out.println("In Derived Class func method");
}
}
class InheritDemo {
public static void main(String [] args) {
Derived D = new Derived();
D.func2();
}
}
It will print:
func2
In base func method
When you change func() in Base to public, then it will be an override, and the output will change to:
func2
In Derived Class func method
No, a private method cannot be overridden because the subclass doesn't inherit its parent's private members. You have declared a new method for your subclass that has no relation to the superclass method. One way to look at it is to ask yourself whether it would be legal to write super.func() in the Derived class. There is no way an overriding method would be banned from accessing the method it is overriding, but this would precisely be the case here.
No, it is not. You can mark an override just to make sure like this:
#Override
public void func(){
System.out.println("In Derived Class func method");
}
And in this case it would be a compiler error.
You are not overriding. You cannot override private members, you are merely defining a new method in Derived. Derived has no knowledge Base's implementation of func() since its declared as private. You won't get a compiler error when you define func() in Derived but that is because Derived does not know Base has an implementation of func(). To be clear: it would be incorrect to say you are overriding Base's implementation of func().
In addition to the already correct answer, consider this:
public class Private {
static class A {
public void doStuff() {
System.out.println(getStuff());
}
private String getStuff() {
return "A";
}
}
static class B extends A {
public String getStuff() {
return "B";
}
}
public static void main(String[] args) {
A a = new A();
a.doStuff();
a = new B();
a.doStuff();
B b = new B();
b.doStuff();
}
}
This will print
A
A
A
although B "overrides" getStuff(). As implementation of doStuff() is fixed to calling A#getStuff(), no polymorphism will be triggered.
Nope because if you do something like Base b = new Derived(); you still won't be able to call b.func(). What you're doing is called "hiding".
Since the method is private it is not visible to the other classes.Hence the derived class does not inherit this method.
So this is not the case of overriding
Method hiding will be happening here instead of overriding. like what happens in case of static.
Actually,you are not overriding.Before Java5
an overridden method's return type must match with parent class's method.
But Java 5 introduced a new facility called covariant return type.You can override a method with the same signature but returns a subclass of the object returned. In another words, a method in a subclass can return an object whose type is a subclass of the type returned by the method with the same signature in the superclass.
you can follow this thread :Can overridden methods differ in return type?
The private member of the base class cannot be access by anyone outside of the class and cannot be overridden. The function in the derive class is an independent function that can be access by anywhere.
The code would run the function in the derived class
A private method can never be over ridden. It is always hidden.
In your example - Derived class has one parent class private method and has its own function func. Both are different, and the func is not over ridden. Its a separate independent function.
If you create a new function in parent class calling parent class function, the parent func will be called, if parent class reference is used as opposed in the case of method over ridding
Note : An object defines the members which it has, and a reference defines which it can access
// Method Over ridding case
class Base{
public void func(){
System.out.println("Parent class");
};
public void func1(){
func();
}
}
class Derived extends Base{
public void func(){
System.out.println("Derived class");
}
}
class InheritDemo{
public static void main(String [] args){
Derived d = new Derived();
d.func1(); // Prints Derived class
Base b = new Derived();
b.func1(); // Prints Derived class - no matter parent reference is calling,as there as method is overridden - Check func1() is in parent class, but id doesn't call parent class func() as the compiler finds a func() method over ridden in derived class
}
}
// Method Hidding case - Private and static methods case
class Base{
private void func(){
System.out.println("Parent class");
};
public void func1(){
func()
}
}
class Derived extends Base{
public void func(){ // Is this a Method Overriding..????
System.out.println("Derived class");
}
}
class InheritDemo{
public static void main(String [] args){
Derived d = new Derived();
d.func1(); // Prints Derived class
Base b = new Derived();
b.func1();
// Prints Parent class - the reason is we are using the parent class reference, so compiler is looking for func() and it founds that there is one private class method which is available and is not over ridden, so it will call it. Caution - this won't happen if called using derived class reference.
b.func();
// this prints the Derived class - the compiler is looking func(), as Derived class has only one func() that it is implementing, so it will call that function.
}
}
Read comments in the below code snippet to find the answer.
Sources:
Definition reference:
Credits for the source code example(reference) from the book - "OCA Oracle Certified Associate Java SE 8 Programmer Study Guide Exam 1Z0-808 Book" from 'Jeanne Boyarsky' and 'Scott Selikoff'.
public class Deer {
public Deer() { System.out.print("Deer"); }
public Deer(int age) { System.out.print("DeerAge"); }
private boolean hasHorns() { return false; }
public static void main(String[] args) {
Deer deer = new Reindeer(5);
System.out.println(","+deer.hasHorns());// false is printed.
}
}
class Reindeer extends Deer {
public Reindeer(int age) { System.out.print("Reindeer"); }
private boolean hasHorns() { return true; } // Overriding possible, but is of no use in the below context.
// Below code is added by me for illustration purpose
public static void main(String[] args) {
Deer deer = new Reindeer(5);
//Below line gives compilation error.
//System.out.println(","+deer.hasHorns());
}
}

How to call a superclass method using Java reflection

I have two classes:
public class A {
public Object method() {...}
}
public class B extends A {
#Override
public Object method() {...}
}
I have an instance of B. How do I call A.method() from b? Basically, the same effect as calling super.method() from B.
B b = new B();
Class<?> superclass = b.getClass().getSuperclass();
Method method = superclass.getMethod("method", ArrayUtils.EMPTY_CLASS_ARRAY);
Object value = method.invoke(obj, ArrayUtils.EMPTY_OBJECT_ARRAY);
But the above code will still invoke B.method().
If you are using JDK7, you can use MethodHandle to achieve this:
public class Test extends Base {
public static void main(String[] args) throws Throwable {
MethodHandle h1 = MethodHandles.lookup().findSpecial(Base.class, "toString",
MethodType.methodType(String.class),
Test.class);
MethodHandle h2 = MethodHandles.lookup().findSpecial(Object.class, "toString",
MethodType.methodType(String.class),
Test.class);
System.out.println(h1.invoke(new Test())); // outputs Base
System.out.println(h2.invoke(new Test())); // outputs Base
}
#Override
public String toString() {
return "Test";
}
}
class Base {
#Override
public String toString() {
return "Base";
}
}
Building on #java4script’s answer, I noticed that you get an IllegalAccessException if you try to do this trick from outside the subclass (i.e., where you would normally be calling super.toString() to begin with). The in method allows you to bypass this only in some cases (such as when you are calling from the same package as Base and Sub). The only workaround I found for the general case is an extreme (and clearly nonportable) hack:
package p;
public class Base {
#Override public String toString() {
return "Base";
}
}
package p;
public class Sub extends Base {
#Override public String toString() {
return "Sub";
}
}
import p.Base;
import p.Sub;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
public class Demo {
public static void main(String[] args) throws Throwable {
System.out.println(new Sub());
Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
IMPL_LOOKUP.setAccessible(true);
MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
MethodHandle h1 = lkp.findSpecial(Base.class, "toString", MethodType.methodType(String.class), Sub.class);
System.out.println(h1.invoke(new Sub()));
}
}
printing
Sub
Base
It's not possible. Method dispatching in java always considers the run-time type of the object, even when using reflection. See the javadoc for Method.invoke; in particular, this section:
If the underlying method is an
instance method, it is invoked using
dynamic method lookup as documented in
The Java Language Specification,
Second Edition, section 15.12.4.4; in
particular, overriding based on the
runtime type of the target object will
occur.
You can't, you'll need an instance of the super class because of the way methods dispatching works in Java.
You could try something like this:
import java.lang.reflect.*;
class A {
public void method() {
System.out.println("In a");
}
}
class B extends A {
#Override
public void method() {
System.out.println("In b");
}
}
class M {
public static void main( String ... args ) throws Exception {
A b = new B();
b.method();
b.getClass()
.getSuperclass()
.getMethod("method", new Class[]{} )
.invoke( b.getClass().getSuperclass().newInstance() ,new Object[]{} );
}
}
But most likely, it doesn't make sense, because you'll loose the data in b.
You can't do that. It would mean polymorphism is not working.
You need an instance of A. You can create one by superclass.newInstance() and then transfer all fields with something like BeanUtils.copyProperties(..) (from commons-beanutils). But that's a 'hack' - you should instead fix your design so that you don't need that.
I don't know how to do it in the case when You want to do the trick for included libraries, because the reflection doesn't work, but for my own code I would do this simple workaround:
public class A {
public Object method() {...}
}
public class B extends A {
#Override
public Object method() {...}
public Object methodSuper() {
return super.method();
}
}
For simple cases this is OK, for some automatic invocation not so much. For instance, when You have a chain
A1 super A2 super A3 ... super An
of inheriting classes, all overriding a method m. Then invoking m from A1 on an instance of An would require too much bad coding :-)
You can create a byte code sequence using a different this pointer before calling invokespecial.
Calling the super.toString() method of any object is like:
ALOAD X ;X = slot of object reference of the object to access
INVOKESPECIAL java/lang/Object.toString ()Ljava/lang/String;
POP
This way creating an anonymous class containing the necessary object is possible.
If you can't modify either class, you need to use reflection to use method handles. You need to use invokespecial calls to call super methods which can be done with MethodHandles. The MethodHandles.lookup() method creates a Lookup instance with the caller class and only permits special calls from that class. To call super methods from any class, get the constructor of Lookup:
var lookupConstructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class);
lookupConstructor.setAccessible(true);
Create an instance of it with class A or B passed as the parameter, and use unreflect with the reflected method object which already points to A internally (or use findSpecial):
var lookup = lookupConstructor.newInstance(B.class);
var method = A.class.getMethod("method");
var mHandle = lookup.unreflectSpecial(method, B.class);
// OR
var mHandle = lookup.findSpecial(A.class, "method", MethodType.methodType(returnType), B.class);
Note that the class specified in the constructor and the last argument of unreflectSpecial/findSpecial must be the same, although it doesn't matter which class it is as long as it's a subclass of A (or A itself).
The resulting MethodHandle ignores any overrides so it will always call the method belonging to the original Method object (A in this case) or the class specified as the first argument of findSpecial. When invoking the method, pass the B object as the first parameter, and any additional arguments:
Object ret = mHandle.invoke(b);

Categories

Resources