2014-04-25 28 views
3

我遇到了下面的java代碼,我不確定它的含義。我們可以在實例化一個類後在'{'中編寫代碼,例如新的TestClass {* /代碼在這裏* /}實例化一個類時聲明函數

但是當我嘗試運行代碼時,在輸出中看不到'Z是10' 。有人可以給我一些鏈接,我可以得到一些有關這個功能的Java更多的信息。

class TestClass { 
    int z; 
    public TestClass(){ 
    z=10; 
    } 
    public int getZ(){ 
    return z; 
    } 
    public void setZ(int z){ 
    this.z=z; 
    } 
} 

class A 
{ 
    public static void main (String[] args) throws java.lang.Exception 
    { 
    TestClass TC = new TestClass() { 
      public void testprint() { 
     System.out.println("Z is " + getZ()); 
     } 
    }; 
    } 
} 

回答

1

做這件事時,你是隱式繼承TestClass和實例化它的時候了,添加一個方法testPrint()

這叫做Anonymous Class

2

這是匿名內部類的例子。它就像一個擴展TestClass的類。所以你不打電話的任何方法,所以它不會打印

8

這是一個匿名的內部類。它創建一個對象,該對象是某個類的子類TestClass的實例,您不希望爲該子類提供一個名稱(因爲您只需要即時創建對象,並且無需在任何地方使用該類其他)。

代碼只初始化對象,實際上並沒有調用正在創建的對象的方法,所以這就是爲什麼你沒有看到任何輸出。你可以添加一行代碼

public static void main (String[] args) throws java.lang.Exception 
{ 
    TestClass TC = new TestClass() { 
     public void testprint() { 
      System.out.println("Z is " + getZ()); 
     } 
    }; 
    // <- call the new method (>_< this won't compile) 
    TC.testprint(); 
} 

除了這一點,因爲testprint沒有定義爲TestClass的方法是行不通的,局部變量引用對象的類型爲TestClass中,所以編譯器能夠找到在TestClass或TestClass的超類上定義的方法。你可以某種方法添加到TestClass中,像這樣:

abstract class TestClass { 
    int z; 
    public TestClass(){ 
     z=10; 
    } 
    public int getZ(){ 
     return z; 
    } 
    public void setZ(int z){ 
     this.z=z; 
    } 
    // add new method 
    public abstract void testprint(); 
} 

現在編譯器知道期待那種類型的TestClass的對象將有一個名爲testprint方法。我不必製作TestClass抽象,我可以添加一個testprint的測試。但是,由於TestClass是抽象的,很明顯新對象不是TestClass,而是它的一些子類。

或者,也可以通過TestClass的另一個已公開的方法調用此方法。用你的TestClass不變,但改變的主要方法:

public static void main (String[] args) throws java.lang.Exception 
{ 
    TestClass TC = new TestClass() { 
     public void testprint() { 
      System.out.println("Z is " + super.getZ()); 
     } 
     // override Z getter to call testprint 
     @Override public int getZ(){ 
      testprint(); 
      return z; 
     } 
    }; 
    TC.getZ(); // <- call method on object created above 
} 

testprint不得不改變調用父類的版本的Z的獲取的,所以我們不會有一個無限遞歸。現在的匿名子類在Z吸氣調用testprint方法,這樣你就可以調用getter和看到輸出:

Z is 10 

的代碼不分配子類的名稱,但它仍然得到一個分配給它。如果我添加一行的主到底看到了什麼匿名類內部調用:

System.out.println(TC.getClass()); 

它打印

class A$1 

在實踐中不能夠直接調用新的方法中定義的一個匿名類不是一個限制。如果要將類的實現傳遞給某個其他對象的方法,則需要提供一個匿名類,該方法需要匿名類的對象不知道(也不應該知道,請參閱LSP)如何無論如何要調用新方法。

+1

問題是,如果testprint()不是TestClass的一個方法,但只在匿名類( - >不覆蓋方法)中定義,則不能像這樣調用它... – Puce

+0

作爲一種替代方法,如果基類沒有定義它,那麼您可以從匿名類的另一個方法或初始化程序中調用該方法。 – Puce

+0

@Puce:謝謝,很好的建議。 –

1

在你的代碼

TestClass TC = new TestClass() { 
      public void testprint() { 
     System.out.println("Z is " + getZ()); 
     } 
    }; 

這就是所謂的Annonymous內部類,所以這隻會初始化。上面的代碼片段後,您可以使用TC.testprint();

注 - TC是好的。但根據Java命名約定規則使用簡單的字母。 您可以從這裏閱讀更多 - http://www.iwombat.com/standards/JavaStyleGuide.html

+0

請注意,您調用TC.testprint的建議不正確,因爲testprint不是TestClass上的一個方法。 (我最初犯了同樣的錯誤。) –

+0

我剛纔看到的優秀點人。非常感謝。看到你編輯了答案,所以我保持原樣。 – ambarox