2011-12-20 83 views
6

我傳遞一個接口作爲匿名執行一個不同的對象是這樣的:傳遞匿名類

public interface Interface { 
    public int convert (int a); 
} 



public static void main(String[] args) throws IOException, InterruptedException { 

    final int[] array = {1,6,3,5,7,8,4,0,3}; 
    Interface inter = new Interface() {   
     public int convert(int a) { 
     int result = a;     
     for (int i = 0; i < array.length; i++) { 
     a=a+array[i]; 
     }    
     return a; 
     } 
    }; 

    SomeObject ty = new SomeObject(); 
    ty.Test(7, inter); 
} 

public class SomeObject { 

    public void Test(int number, Interface inter) {    
    System.out.println(inter.convert(number)); 
    } 
} 

我的問題是:它是如何工作的? SomeObject如何知道未直接傳遞給對象的數組(數組不是匿名類的成員)。

更新
(對不起,遲到更新)

什麼有關成員瓦爾或在匿名類使用的方法的方法呢?他們不是最終

Interface inter = new Interface() {    
      public int convert(int a) { 
      int result = a + someMemberVar;     
      for (int i = 0; i < array.length; i++) { 
      a=a+array[i]; 
      }    
      return a; 
      } 
     }; 
+1

行'int result = a;'的目的是什麼? – 2011-12-20 15:31:31

回答

2

我的問題是如何工作的呢? SomeObject如何知道沒有直接傳遞給對象的數組 (數組不是 匿名類的成員)。

  • 答:,沒有關係。除非你聲明array是最終的。
  • 推理:它的工作原理(如果數組是最終的),因爲它是最終的,因此匿名函數知道 該數組不能更改。

什麼有關成員瓦爾或方法,這些方法在 匿名類使用的方法?他們不是最終

  • 答:實例變量和方法(以及靜態變量和方法)的範圍,無論如何,在創建匿名類時。
+0

是的,它是最終的。抱歉 – omrid 2011-12-20 15:30:43

+0

所以它的當前狀態的整個數組傳遞給SomeObject作爲常量? – omrid 2011-12-20 15:35:35

+1

只有對數組對象的引用纔會傳遞給匿名類。如果聲明方法更改了數組*元素*,匿名類將會看到這一點。 – 2011-12-20 15:47:36

2

因爲方法局部變量是直接在方法塊中聲明的,所以它只在方法中可見,從聲明後的下一個語句開始。而通過method-local我是指在方法中聲明的變量,但在可能出現在該方法內的任何其他塊(例如while { /* not here */ })之外。

如果您看到,在array的聲明之後,您的匿名類也被定義爲同一方法中的本地類。這就是爲什麼這個課堂可以看到它。

您需要使arrayfinal能夠在匿名類中使用它的原因是,局部變量只存在於該方法存在之前,但本地類的對象可能活得更長(即使在方法完成後)。

+0

可見性實際上也受到塊的限制。所以它不是方法內的局部變量,但它也必須位於同一個塊內。 – Stefan 2011-12-20 16:20:51

+0

@Stefan:沒錯。 – 2011-12-20 16:25:20

+0

@Stefan:謝謝。將其從本地更改爲方法本地。 – 2011-12-20 16:30:25

0

您正在將可訪問數組的對象接口傳遞給SomeObject方法。

因此,SomeObject使用的是您在main上傳遞的相同對象接口。

因爲Interface可以訪問數組,所以可以使用它。

它不是使用數組的SomeObject。它是Interface對象。

+0

匿名類有權訪問其封閉方法的最終變量 – pringi 2011-12-20 15:43:57

0

Java保留對內部類中使用的封閉類的所有(最終)對象的引用。如果你想知道這個把戲是怎麼女僕,添加以下行測試方法:

System.out.println(inter.getClass().getDeclaredConstructors()[0].getParameterTypes()[0].getCanonicalName() 

而且你的輸出將是「INT []」

,編譯器簡單創建了一個構造函數內部類並將其傳遞給它所需的字段

+0

我已經添加了最終的代碼:) – omrid 2011-12-20 15:46:57

+0

我刪除了最終的相關東西 – 2011-12-20 15:48:10

1

這是Java的範圍和可見性規則的一部分。在您當前的示例中,其名稱爲Closure。基本上,塊中定義的所有內容在該塊內都可見。舉一個例子,這是有效的Java代碼(在方法中的任何地方):

{ 
    final int i = 5; 
    // do somthing with i 
} 
// cant refernce i here 
{ 
    final int i = 6; 
    // do somthing with i 
} 
// cant refernce i here 

自定義塊內一個新的類(我wouldnt工作,如果你只是實例化的話)它看到在同一個塊中聲明的一切。 Java提出的唯一限制就是你不能在第一次賦值之後改變它的值,以避免引用'轉義'它的塊(多線程,生命期比聲明塊等長)的問題。如果你聲明方法的最終參數,你也可以使用它們,因爲它們是在同一個塊內定義的。

所以,如果你改變了你的代碼,這

 { 
      final int[] array = {1,6,3,5,7,8,4,0,3}; 
     } 
     Object inter = new Object() 
     {   
      public void test() 
      { 
       System.out.println(array); 
      } 
     }; 

這是行不通的(嘗試)。