views:

64

answers:

3

Running this code:

class A {                                                                       
  public int x;                                                                 
  public A() {                                                                  
    function();                                                                 
  }                                                                             
  public void function() {                                                      
    this.x = 20;                                                                
  }                           
  public void printhey() { System.out.println("Hey"); }                                             
}                                                                               

class B extends A {   
  public B() {
    super();
    printhey(); 
  }                                                          
  public void function() {                                                      
    this.x = 50;                                                                
  }                                                                             
}                                                                               

public class tmp {                                                              
  public static void main(String[] args) {                                      
    System.out.println((new B()).x);                                            
  }                                                                             
}

prints out:

Hey
50

Who sets up the VTBL? in A's constructor, function is already set to be B. But in B's constructor, printhey is set up to be A's.

A: 

The simple answer is, 'The JVM, of course'. By the time B is loaded, the JVM has complete knowledge of the class hierarchy, and has resolved all the references. It's not like C++. Of course, I'm interpreting you as using the term VTBL metaphorically. There's no actual data structure much like a VTBL in any serious JRE.

bmargulies
what do you mean by "constructors are not allowed to call non-final public members"? I just called printhey() in A's constructor.
Claudiu
Whoops, I was remembering a PMD flag which prevents this and mistakenly called it a java requirement. Edit coming up.
bmargulies
+2  A: 

There is no concept of a VTBL in Java; ergo, there is no VTBL.

The object created is a new B(), and B has (by then) a function (defined in B, since it overrides A's) and printhey (inherited from A). So X gets assigned to 50 - A's constructor, invoked via B's constructor, does the set operation by calling 'function' (from B). We then invoke 'printhey' (line after super() in B) which calls the inherited fn. Then, we return the instance, from which X is obtained, so you see 50.

AlBlue
so functions aren't implemented using VTBLs?
Claudiu
No, VTBLs are a C++ concept.
AlBlue
VTBLs are the simplest way to implement virtual dispatch, but there are others. However, that's just an implementation detail
erikkallen
+5  A: 

"VTBL"s are an artifact of languages that deal in Storage Structures. That is, in C++, you can deduce with a fair degree of accuracy exactly how a class will map in RAM.

Java doesn't deal with Storage Structures, it deals with Data Structures. You can easily use a Storage Structure as a Data Structure, but the reverse isn't as trivial. If you happen to have a copy of BYTE magazine from back in early 1991, you can even find the article where I extolled the virtues of mapping C++ data structures onto the storage structures used by the Commodore Amiga OS ROM Kernel (Exec). Back then, in fact, the term "data structure" was used as a sort of catch-all, since we still worried about how things would fit precisely into memory.

Data Structures are generally used by algorithms. Storage Structures are more closely related to internal implementations and serialized forms. Actual program execution requires a little bit of both, but the Storage Structures underlying a Java Data Structure are supposed to be opaque. It's a large part of what makes Java "Write Once, Run Anywhere". If you don't have to worry about the size and byte orientation of things, you don't have to load down your app with "swabbers" and memory-offset calculators.

Some programming languages don't like forward and circular references. Java would be hard put to do without them. However, there's a difference between a hard reference to code and a reference to a method signature that's bound to a bytecode and which will (possibly) eventually be JIT-compiled to machine code. Or even re-optimized and recompiled, in some of the more advanced JVMS. What it all boils down to is that you have, in effect, multiple passes over the class, where one establishes the dictionary and another plugs in the linkages. Including automatic inlining, if appropriate.

Tim Holloway
very nice answer, ty. i got the idea from the other answers but this is much more explanatory.
Claudiu