我已经阅读了一些关于这个主题的帖子:
-
static allocation in java - heap, stack and permanent generation
-
where is a static method and a static variable stored in java. In heap or in stack memory
但我对它们所说明的概念感到困惑:
静态方法(实际上是所有方法)以及静态变量都存储在堆的PermGen部分中,因为它们是反射数据的一部分(类相关数据,而不是实例相关) .
因此,无论是否 static
,方法仅存储在类中的堆上的一个副本 . 现在只有一个副本在类中,我解释为所有方法都属于该类,那么为什么Java只能使用实例化的实例调用非静态方法?
为什么我们有非静态方法属于实例的概念,而不是类?
1 回答
这个故事的另一面需要提及 . 有课时,请说
Bar
:在堆上,
doSomethingElse
的签名不是doSomethingElse()
,而是doSomethingElse(Bar this)
. 与没有参数的doSomething
相反(因此你不能从静态方法调用this
- 没有this
来调用) .当你有这样的电话时:
它只是一个语法糖:
定义扩展类
Foo
时:另一种方法是创建
doSomethingElse(Foo this)
. 接下来就是一个虚拟表(如果你不熟悉这个术语,请阅读它) - 每个类都有一个虚拟表,它将方法签名映射到具体代码 . 在运行时调用方法时,根据实例的动态类型,在类(而不是实例)虚拟表中搜索正确的实现 .所以完整的例子就是(当然这只是一个简化):
Java syntax (syntactic sugar):
What really happens (simplified):
这当然只是一种简化,但就像它发生的那样 .
事实上,当你想到它时,所有方法在内存中都是静态的(这就是它们驻留在
PermGen
中的原因) . 编译器为每个类使用静态虚拟表,以便调用正确的方法 . 这允许多态性 .