2012-04-01 61 views
4

有沒有辦法訪問匿名外部類?一個普通的類可以被ClassName.this訪問。這是行不通的,因爲一個匿名類顯然沒有名字。我也嘗試使用擴展類/接口(如Runnable.this),但它似乎不會像這樣工作。我敢肯定,這可能不是最好的編碼風格,我只是好奇,如果有可能沒有將這個外部存儲在變量中。訪問匿名外部類而不存儲在變量中?

實施例,注意outer.this:

public class A 
{ 
    public static void main(String[] args) { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       new Thread(new Runnable() { 
        @Override 
        public void run() { 
         synchronized (outher.this) { 
          outher.this.notify(); 
         } 
        } 
       }).start(); 
       try { 
        synchronized (this) { 
         wait(); 
        } 
       } catch (final InterruptedException ex) {} 
      } 
     }).start(); 
    } 
} 

回答

2

沒有,沒有辦法從任何地方訪問匿名類,除了從在其內部(即,並非由this參考)。或者通過顯式聲明的變量。

final Runnable r1 = new Runnable() {...}; 
Runnable r2 = new Runnable() { 
    public void run() { 
     synchronized(r1) {...} 
    } 
}; 
+0

你認爲它可以與匿名類一起使用synchronized(this.getClass()。getEnclosingClass())嗎? – 2012-04-01 18:22:12

+0

@Eric R.我認爲這會做與DiddiZ發佈的不同的東西(也許你提出的是DiddiZ真正想要的)。假設'main'方法在許多不同的線程中同時執行。在DiddiZ的代碼中,它們都將同步在不同的對象上 - 因此不會發生衝突。在你的代碼中,它們都將在同一個對象上同步,所以會有一些衝突。但我懷疑你的代碼是DiddiZ真正想要的。 – emory 2012-04-01 18:35:22

+0

這是按類同步的,而不是實例。如果更改同步監測到同步(this.getClass()。getEnclosingClass())和synchronized(this.getClass())(而不是同步(this)),這將工作。但是,如果您在同一個Runnable實例上運行多個線程,它將像靜態同步 - 即跨所有實例。 – 2012-04-01 18:39:10

1

你可以添加一個方法來返回這個中間this。這將在範圍內,但不隱藏(是否是正確的術語?陰影?我忘記了。)。

public static void main(String[] args) { 
    new Thread(new Runnable() { 
     Runnable middleThis() { return this; } // <-- this 
     @Override 
     public void run() { 
      new Thread(new Runnable() { 
       @Override 
       public void run() { 
        synchronized (middleThis()) { 
         middleThis().notify(); 

請注意,雖然匿名內部類沒有名稱,但它們仍然是類型。所以添加成員對立即表達式(new X() { Y z; }.z)和內部是可見的。你不能做middleThis().middleThis()

+0

這是一種巧妙解決「不存儲在變量中」限制的方法。 – emory 2012-04-01 18:49:29