If an instance method is added to a subclass and it overrides a method in a superclass, then the subclass method will be found by method invocations in pre-existing binaries, and these binaries are not impacted. If a class method is added to a class, then this method will not be found, because the invocation of a class method is resolved at compile time to use the fully qualified name of the class where the method is declared. Thus if the example:
class Hyper {
void hello() { System.out.print("Hello, "); }
static void world() { System.out.println("world!"); }
}
class Super extends Hyper { }
class Test {
public static void main(String[] args) {
Super s = new Super();
s.hello();
s.world();
}
}
is compiled and executed, it produces the output:
Hello, world!
Suppose that a new version of class Super is produced:
class Super extends Hyper {
void hello() { System.out.print("Goodbye, cruel "); }
static void world() { System.out.println("earth!"); }
}
If Super is recompiled but not Hyper or Test, then running the new binary with
the existing binaries for Hyper and Test will produce the output:
Goodbye, cruel world!
This example demonstrates that the invocation in:
s.world();
in the method main is resolved, at compile time, to a symbolic reference to the
class containing the class method world, as though it had been written:
Hyper.world();
This is why the world method of Hyper rather than Super is invoked in this
example. Of course, recompiling all the classes to produce new binaries will allow
the output:
Goodbye, cruel earth!