If non-static
functions are copied into the heap f开发者_如何学Pythonor each object that has that method, then why aren't all methods in Java static
by default? Why waste all of that heap memory this way?
A diagramic explanation would be more helpful for me to understand this.
Static methods cannot access an object's instance member variables... No state, no OOP.
Typically, Java methods are not implemented by copying the method onto the heap once per object. Instead, methods are typically implemented using something called a virtual function table (or "vtable"). The idea is that there is exactly one copy of each method, whether it's a static or nonstatic method, and pointers to these methods are laid out into a table. Each object in the heap then stores a pointer to the vtable for its object type. This means that the size of any heap object does not depend on the number of methods the object has. In fact, an object with 100 methods would be the same size an object with 1 method (assuming they have the same fields). Each just stores a pointer to the vtable for its object type, of which there's only one copy.
This optimization was originally used in C++ to support fast virtual functions and has since been used in many other object-oriented languages. It allows objects to be small, yet support dynamic dispatch.
In other words, methods don't need to be static
by default because they don't contribute to the size of the objects in the heap. Creating an object doesn't take longer for objects with more functions, or does it use more heap space.
Here's one possible diagram for the layout of some objects (apologies for ASCII art!). Suppose that we have two classes, A and B. Then in memory, objects of those types might look like this:
A vtable for A
+-------------+ +---------------+
| vtable ptr | --+-> | method one |
+-------------+ | +---------------+
| | | | method two |
| fields of A | | +---------------+
| | | | ... |
+-------------+ | +----------------
| | method N |
A | +---------------+
+-------------+ |
| vtable ptr |---+
+-------------+
| |
| fields of A |
| |
+-------------+
B vtable for B
+-------------+ +------------+
| vtable ptr | --> | method one |
+-------------+ +------------+
| | | method two |
| fields of B | +------------+
| | | ... |
+-------------+ +------------+
| method M |
+------------+
Notice how both objects of type A share the same vtable, and how objects of types A and B only use the same amount of space for their vtable pointer, even if they have different numbers of methods.
Your question is for a comparison between procedural and object-oriented programming. http://en.wikipedia.org/wiki/Procedural_programming#Comparison_with_object-oriented_programming. The primary motivation for OO versus procedural is to have data structures capable of performing actions themselves.
As for the assumptions about memory allocation, methods are not copied to each object because Java does not support dynamic type modification. For example, if an object is of type Foo, then it will have all of the methods declared by type Foo. New methods cannot be added to instances of Foo without changing the type itself. Whenever a method is called on an object, behind the scenes it is run as a procedure.
Whenever you run this:
foo.say( "Hello, world!" );
Java actually does something like this:
- Create the string "Hello, world!"
- Look for the type declared for
foo
. - Look for a method with the signature
say(String)
in that type. - Run that method using the
foo
object's instance state.
Because methods maintain their own state, any non-static method can be implemented in a static way by passing the object instance in as a method parameter. In fact, step 4 above is likely implemented this way by the Java compiler.
Because if every method was static java would not be object-oriented.
You need to invoke a method on different objects, because they have different state.
As for the memory - each static invocation also goes on the stack.
The code of the method is not on the stack, it is in a part of the heap (the permanent generation, special-cased by the garbage collector). On the stack only the local variables of the method (and similar runtime-data, like return address) are located.
This is independent of them being static or non-static methods.
Also, the code of the method will not be copied for each object of the class - just when executing the method, it gets an additional argument, which points to the object on which it is invoked. This single argument is the only memory overhead between static and nonstatic methods.
精彩评论