It is actually late binding, not early binding. Early binding only happens for non-overrideable methods.
Given this code:
public class Test
{
void foo()
{
System.out.println("foo");
}
final void bar()
{
System.out.println("bar");
}
void car(String s)
{
System.out.println("car String");
}
void car(Object o)
{
System.out.println("car Object");
}
static void star()
{
System.out.println("star");
}
public static void main(final String[] argv)
{
Test test;
Object a;
Object b;
test = new Test();
a = "Hello";
b = new Object();
test.foo();
test.bar();
test.car(a);
test.car(b);
Test.star();
}
}
The javac I used generates this for main:
public static void main(java.lang.String[]);
Code:
0: new #9; //class Test
3: dup
4: invokespecial #10; //Method "<init>":()V
7: astore_1
8: ldc #11; //String Hello
10: astore_2
11: new #12; //class java/lang/Object
14: dup
15: invokespecial #1; //Method java/lang/Object."<init>":()V
18: astore_3
19: aload_1
20: invokevirtual #13; //Method foo:()V
23: aload_1
24: invokevirtual #14; //Method bar:()V
27: aload_1
28: aload_2
29: invokevirtual #15; //Method car:(Ljava/lang/Object;)V
32: aload_1
33: aload_3
34: invokevirtual #15; //Method car:(Ljava/lang/Object;)V
37: invokestatic #16; //Method star:()V
40: return
}
invokevirtual means late binding, invokestatic and invokespecial means early binding.
The line:
24: invokevirtual #14; //Method bar:()V
refers to a non-overrideable method, so logically speaking it should be invokespecial. The runtime is apparently free to make the change when the class is loaded (I could be wrong on that, I haven't delved that deeply into the VM internals, but from what I read it seems that is the case).
So your question is really why doesn't java have what is called Multiple Dispatch (wikipedia link here) which is where the runtime decides what method to call based on the value in the variable instead of basing it on what the variable is declared as.
The way the compiler works is to say something like:
- I am calling SomeClass.doSomething on
a variable declared to be an Object.
- Does SomeClass have a method called
doSomething that takes an Object?
- If yes, then output an invokevirtual
call to that method.
What you are wanting is an additional step that happens at runtime (it could not happen at compile time) that says:
- The variable is pointing at an
Integer.
- I am calling the
SomeClass.doSomething method.
- Call the best match of
SomeClass.doSomething method that
takes an Integer, a Number, an Object
(call whichever it finds first).
Java doesn't to that at runtime, instead it simply calls the method that the compiler decided to call.
You can simulate multiple dispatch in Java like so.