2011-03-07 90 views
21

我正在查看從Java字節碼中獲得的一些反彙編代碼。我看到一些聲明如下:「靜態合成」是什麼意思?

.method static synthetic access$0()Lcom/package/Sample; 

我無法弄清楚什麼syntheticaccess$0意思。有人能幫我理解這個部分嗎?

+2

我不能相信這是不自然! – Mehrdad 2011-03-07 17:57:20

回答

26

在java語言中,內部類可以訪問其封閉類的私有成員。但是,在Java字節碼中,內部類的概念不存在,並且私有成員不可訪問。要解決此問題,編譯器會在外部類中創建綜合訪問器方法。我相信這就是你在這裏看到的。 access$0只是方法的名稱。我不確定synthetic會做什麼。它可能只是隱藏其他編譯器的方法來確保封裝。

2

在Oracle JDK 1.8.0_45斷言是產生static synthetic字段的一個示例:

public class Assert { 
    public static void main(String[] args) { 
     assert System.currentTimeMillis() == 0L; 
    } 
} 

基本上編譯爲:

javac Assert.java 
javap -c -constants -private -verbose Assert.class 

public class Assert { 
    // This method is synthetic. 
    static final boolean $assertionsDisabled = 
     !Assert.class.desiredAssertionStatus(); 
    public static void main(String[] args) { 
     if (!$assertionsDisabled) { 
      if (System.currentTimeMillis() != 0L) { 
       throw new AssertionError(); 
      } 
     } 
    } 
} 

這可以與被驗證

其中包含:

static final boolean $assertionsDisabled; 
    descriptor: Z 
    flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC 

合成字段使得爪哇只需要在加載時調用一次Assert.class.desiredAssertionStatus()產生,然後將其高速緩存其結果存在。

參見:https://stackoverflow.com/a/29439538/895245了更詳細的解釋。

注意,這個合成領域可以產生命名衝突,我們可以定義等多個領域。例如,下面的編譯失敗在Oracle JDK 1.8.0_45:

public class Assert { 
    static final boolean $assertionsDisabled = false; 
    public static void main(String[] args) { 
     assert System.currentTimeMillis() == 0L; 
    } 
} 

唯一令「防止」,即不使用美元,對你的標識符的命名規則。另請參見:When should I use the dollar symbol ($) in a variable name?

獎勵:

static final int $assertionsDisabled = 0; 

會的工作,因爲不像Java的字節碼可以使用相同的名稱,但不同類型的多個領域:Variables having same name but different type