为什么不是每个方法都是静态方法?

问题描述 投票:-8回答:5

如果将非static函数复制到具有该方法的每个对象的堆中,那么为什么默认情况下不是Java static中的所有方法都没有?为什么要这样浪费所有的堆内存?

图解说明将有助于我理解这一点。

java methods static
5个回答
2
投票

通常,Java方法是通过每个对象一次将方法复制到堆上而实现的。取而代之的是,通常使用称为v​​irtual function table(或“ vtable”)的东西来实现方法。这个想法是每个方法只有一个副本,无论是静态方法还是非静态方法,并且这些方法的指针都放置在一个表中。然后,堆中的每个对象都会为其对象类型存储指向vtable的指针。这意味着任何堆对象的大小都不取决于该对象拥有的方法的数量。实际上,具有100个方法的对象与具有1个方法的对象具有相同的大小(假设它们具有相同的字段)。每个对象都只存储一个指向其对象类型的vtable的指针,该对象只有一个副本。此优化最初在C ++中用于支持快速虚拟函数,此后已在许多其他面向对象的语言中使用。它允许对象较小,但支持动态分配。

换句话说,方法不必默认为static,因为它们不会增加堆中对象的大小。对于具有更多功能的对象,创建对象不会花费更长的时间,也不会占用更多的堆空间。

这是一些对象的布局的可能示意图(为ASCII艺术表示歉意!)。假设我们有两个类,A和B。然后在内存中,这些类型的对象可能看起来像这样:

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 | +------------+

注意类型A的两个对象如何共享相同的vtable,以及类型A和B的对象如何仅为其vtable指针使用相同的空间,即使它们具有不同数量的方法。

1
投票
静态方法无法访问对象的实例成员变量...没有状态,没有OOP。

1
投票
您的问题是在过程式编程和面向对象的编程之间进行比较。 http://en.wikipedia.org/wiki/Procedural_programming#Comparison_with_object-oriented_programming。面向对象与程序的主要动机是拥有能够自行执行操作的数据结构。

0
投票
因为如果每个方法都是静态的,java都不是面向对象的。

0
投票
该方法的代码不在堆栈上,而是在堆的一部分中(永久生成,由垃圾收集器进行特殊处理)。在堆栈上,仅定位方法的局部变量(以及类似的运行时数据,如返回地址)。
© www.soinside.com 2019 - 2024. All rights reserved.