Q:

why base class method is invoked?

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");
    }
}

A:

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?

