簡體   English   中英

Java內部可見性難題

[英]Java inner class visibility puzzle

考慮以下情況:

public class A {
  public A() { b = new B(); }
  B b;
  private class B { }
}

從Eclipse中的警告我引用:java complier通過合成訪問器方法模擬構造函數AB()。 我想編譯器現在繼續為B創建一個額外的“水下”構造函數。

我覺得這很奇怪:為什么B級不能作為A中的ako場可見? 並且:這是否意味着B類在運行時不再是私有的? 並且:為什么表示B類的受保護關鍵字不同?

public class A {
  public A() { b = new B(); }
  B b;
  protected class B { }
}

內部類本質上是Java 1.1中引入的一個hack。 JVM實際上沒有內部類的任何概念,因此編譯器必須提供它。 編譯器在類A的“外部”生成類B,但是在同一個包中,然后向其添加合成訪問器/構造函數以允許A訪問它。

當你給B一個受保護的構造函數時,A可以訪問該構造函數,因為它在同一個包中,而不需要添加合成構造函數。

我知道這個問題現在已經快三年了,但我發現問題的一部分仍未得到解答:

並且:這是否意味着B類在運行時不再是私有的?

Carlos Heubergers對skaffmans的回答表明, B類對於其他類別的包仍然是private的。

他可能適合Java編程語言,即不可能從其他類引用B類。 至少沒有使用反射(也可以從外部訪問私有類成員),但這是另一個問題。

但由於JVM沒有內部類的任何概念(如skaffman所述),我問自己如何在字節碼級別實現“只能通過一個類訪問”的可見性。 答案:它根本沒有實現,對於JVM,內部類看起來像普通的包私有類。 這是,如果您自己編寫字節碼(或修改編譯器生成的字節碼),您可以毫無問題地訪問B類。

您也可以從同一個包中的所有類訪問所有合成訪問器方法。 因此,如果在類B的方法中為類A的私有字段分配值,則會在類A (名為access$000 )中生成具有默認(即包私有)可見性的合成訪問器方法,該方法為您設置值。 該方法應該只從類B調用(實際上它只能使用Java語言從那里調用)。 但是從JVM的角度來看,這只是一種方法,可以被任何類調用。

那么,回答這個問題:

  • 從Java語言的角度來看, B類是保持私有的。
  • 從JVM的角度來看, B類(或更好: A$B類)不是私有的。

class B及其構造函數的訪問不必相同。 你可以擁有一個帶有包范圍構造函數的私有內部類,這就是我通常所做的。

public class A {
  public A() { b = new B(); }
  B b;
  private class B {
    B() { }
  }
}

你需要使用

this.new B();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM