Question

I have already read some posts on this topic:

But I am confused by the concept they illustrate:

Static methods (in fact all methods) as well as static variables are stored in the PermGen section of the heap, since they are part of the reflection data (class related data, not instance related).

So methods, whether static or not, are only stored for one copy on the heap in the class. Now that there is only one copy which is in the class, which I interpreted as all methods belong to the class, then why can Java only call a non-static method using an instantiated instance?

Why do we have the concept that non-static methods belong to the instance, not the class?

Was it helpful?

Solution

There's another side of the story that needs to be mentioned. When you have a class, say Bar:

public class Bar {
   public static void doSomething() { ... }

   public void doSomethingElse() { ... }
}

On the heap the signature for doSomethingElse is not doSomethingElse() but doSomethingElse(Bar this). As opposed to doSomething which is left with no parameters (hence you can't call this from a static method - there is no this to call to).

When you have a call like this:

Bar bar = new Bar();
bar.doSomethingElse();

It's just a syntactic sugar to:

doSomethingElse(bar); // I neglected here for simplification but the name of the method in the compiled code also includes the name of the class.

When you define an extending class Foo:

public class Foo extends Bar {
    @Override
    public void doSomethingElse() { ... }
}

Another method is created doSomethingElse(Foo this). Next thing to there is a virtual table (read about it if you're not familiar with the term) - Each class holds a virtual table which maps a method signature to a concrete code. When you call a method in runtime there is a search in the class (not the instance) virtual table for the correct implementation according to the dynamic type of the instance.

So the full example would be (and of course that's just a simplification):

Java syntax (syntactic sugar):

Bar b = new Foo();
b.doSomethingElse();

What really happens (simplified):

// Step 1: Get the correct overriden method for Foo class from the virtual table
// Step 2: Invoke the method with the instance "b" as the first parameter (the "this" parameter)
Foo.getMethodFromVirtualTable("doSomethingElse").invoke(b);

That's only a simplification of course but that's sort of the way it happens.

In fact when you come to think of it, all the methods are static in memory (that's why they reside in PermGen). The complier uses the static virtual table for each class in order to call the correct method. This what allows polymorphism.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top