1

這些不同的方法類型在內存中如何處理?內存中的靜態方法和實例方法

我發現了兩個不同的解釋,這樣的:

  1. 靜態方法是隻在內存中一次,而實例方法是在內存中多次,每個實例中的每個實例正確處理好membervariables引用。

  2. 所有方法在內存中只有一次,實例方法只獲取對象的實例作爲參數。

不同的編譯器使用什麼方式?

+0

所有編譯器都使用(2) – 2010-02-05 09:05:46

+0

#2方法聽起來比#1更合乎邏輯。 – Dor 2010-02-05 09:06:35

+0

@尼爾,當然是所有?你怎麼能這麼肯定? – 2010-02-05 09:23:43

回答

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

兩者在內存中只有一次。唯一的區別是實例方法獲得另一個第一個參數:類本身的實例。

什麼確實在內存中存在多次(至少對於.NET)是泛型類和它們各自的具體用途。如果您同時使用List<int>List<string>,那麼您最終將得到兩個JITted代碼拷貝,一個針對int,一個針對string

0

實例方法可以是虛擬的。因此,對於具有虛擬方法的對象的每個運行時實例,運行時環境保持對虛擬方法的引用的管理。但是這些方法只能在內存中存在一次(但是它是運行時環境,它決定了它在內存中加載方法的次數)。

對於非虛擬方法,可以在編譯器時確定引用。