1
votes

This wikipedia states:

Since the specific type of a polymorphic object is not known before runtime (in general), the executed function is dynamically bound. Take, for example, the following Java code:

 public void foo(java.util.List<String> list) {
     list.add("bar");  
 }

List is an interface, so list must refer to a subtype of it. Is it a reference to a LinkedList, an ArrayList, or some other subtype of List? The actual method referenced by add is not known until runtime.

Consider this example:

List<String> list;

list = new LinkedList<String>();
foo(list);

list = new ArrayList<String>();
foo(list);

Why is the actual method referenced here is not know until runtime? Couldn't the compiler just check for each call of foo of which type the object list is assigned to? Of course this would be only possible if the program is deterministic and no randomness is involved (e.g. user interaction).

Is this what (in general) in the quoted statement is about or is my understanding wrong?

In the special case when the program is deterministic, is static binding used or is - in Java - always dynamic binding used, regardless of what is possible? If so, why?

2
It could, but that would be a lot of work for not much gain. - Oliver Charlesworth
@OliverCharlesworth, the gain is great and outweights the a lot of work, thus it actually does this! - Tagir Valeev

2 Answers

2
votes

The statement speaks about the general case. Given only the code of the Wikipedia example it is not possible to tell the concrete type of the list parameter. In your example it is possible to tell the concrete types.

The Java runtime is allowed and does in fact devirtualize method calls if it can detect the concrete type of a variable.

If you are interested in the topic: Here is a link to paper which discusses devirtualization techniques.

1
votes

The devirtualization is not preformed during the compilation of java source to java bytecode. Otherwise this would be quite fragile. Note that compiled java classes usually preserve binary compatibility (with some known exceptions). Thus if your foo is located in the separate class and you recompile just this class, then the class calling foo should work with new code without recompilation.

However the devirtualization is possible at runtime and actually performed by most of modern JVMs (including Oracle HotSpot JVM, or course). This method is likely to be fully inlined during the JIT-compilation: both foo calls, LinkedList.add and ArrayList.add methods will be merged into the body of caller method.

So in general Wikipedia quote is correct: The actual method referenced by add is not known until runtime. However this does not mean that the call remains polymorphic as JVM runtime is quite complex thing which includes interpreter, JIT-compilation and execution of JIT-compiled code.