gpt4 book ai didi

java - 了解堆上静态和非静态方法表示之间的区别

转载 作者:搜寻专家 更新时间:2023-11-01 02:09:02 27 4
gpt4 key购买 nike

我已经阅读了一些关于这个主题的帖子:

但我对他们说明的概念感到困惑:

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).

因此,方法,无论是否为 static,都只在类的堆上存储一个副本。既然类中只有一个副本,我解释为所有方法都属于类,那么为什么 Java 只能使用实例化实例调用非静态方法?

为什么我们会有非静态方法属于实例而不属于类的概念?

最佳答案

故事的另一面需要提及。上课时说Bar:

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

public void doSomethingElse() { ... }
}

在堆上,doSomethingElse 的签名不是doSomethingElse(),而是doSomethingElse(Bar this)。与没有参数的 doSomething 相反(因此您不能从静态方法调用 this - 没有要调用的 this到)。

当你接到这样的电话时:

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

它只是一个语法糖:

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

当你定义一个扩展类 Foo 时:

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

创建了另一个方法 doSomethingElse(Foo this)。接下来是一个虚拟表(如果您不熟悉这个术语,请阅读它)——每个类都有一个虚拟表,它将方法签名映射到具体代码。当您在运行时调用方法时,会根据实例的动态类型在类(而非实例)虚拟表中搜索正确的实现。

所以完整的例子是(当然这只是一个简化):

Java语法(语法糖):

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

真正发生了什么(简化):

// 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);

这当然只是一种简化,但事情就是这样发生的。

事实上,当你想到它时,所有的方法在内存中都是静态的(这就是它们驻留在 PermGen 中的原因)。编译器为每个类使用静态虚拟表来调用正确的方法。这就是允许多态性的原因。

关于java - 了解堆上静态和非静态方法表示之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22579387/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com