内存中的静态方法和实例方法

时间:2010-02-05 09:02:05

标签: compiler-construction memory-management frameworks theory

如何在内存中处理这些不同的方法类型。

我发现了两种不同的解释:

  1. 静态方法只在内存中存在一次,而实例方法在内存中多次,每个实例一个,以便在每个实例中正确处理对成员变量的引用。

  2. 所有方法在内存中只有一次,而实例方法只将对象的实例作为参数。

  3. 不同的编译器使用什么方式?

3 个答案:

答案 0 :(得分:2)

正如约翰内斯所说,简短的答案几乎总是#2。两者都只存在于单个位置的内存中,但实例方法具有上下文(基本上是一个额外的隐藏参数),可以让它们访问实例。

但是:有些语言/环境会实例化一个函数,它看起来(对于源代码的天真读取)就像一个函数一样多次。 JavaScript是一个很好的例子:函数对象关闭它定义的范围,因此如果有多个范围(例如一个函数被多次调用),则会产生多个不同的函数对象。 (口译员/ JIT-ers可以优化代码是否重复,但从概念上来说它是和函数引用不同。)

这是JavaScript中的一个示例:

function foo() {

    alert("hi there");
}

function buildBar(x) {

    function bar() {
        alert(x);
    }

    return bar;
}

var f1, f2;

f1 = foo;
f2 = foo;
f1();
// alerts "hi there"
f2();
// alerts "hi there"
alert("f1 === f2 ? " + (f1 === f2));
// alerts "true", there is only one `foo`

var b1, b2;

b1 = buildBar("one");
b2 = buildBar("two");
b1();
// alerts "one"
b2();
// alerts "two"
alert("b1 === b2 ? " + (b1 === b2));
// alerts "false", there are two `bar`s

这在JavaScript中的“私有”实例数据的某些实现中变得相关,其中人们在构造函数中定义实例方法(就像buildBar定义bar),因此他们可以访问声明的私有变量在构造函数中。这具有所需的效果(私有实例数据),但是多个函数实例的影响 - 对象的每个实例都有一个。

答案 1 :(得分:1)

两者都只在内存中存在一次。唯一的区别是实例方法得到另一个第一个参数:类本身的实例。

在内存中多次存在(至少对于.NET)是泛型类及其各自的特定用途。如果同时使用List<int>List<string>,则最终会得到两个代码的JITted副本,一个针对int,一个针对string

答案 2 :(得分:0)

实例方法可以是虚拟的。因此,对于具有虚方法的对象的每个运行时实例,运行时环境保持对虚方法的引用的管理。但是这些方法只需要在内存中存在一次(但是运行时环境决定了它在内存中加载方法的次数)。

对于非虚方法,可以在编译时确定引用。