2009-07-02 99 views
35
C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet>dir 
Volume in drive C has no label. 
Volume Serial Number is 2041-64E7 

Directory of C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet 

2009-07-02 23:54    . 
2009-07-02 23:54    .. 
2004-09-06 14:57    582 WelcomeApplet.html 
2004-09-06 15:04    1,402 WelcomeApplet.java 
       2 File(s)   1,984 bytes 
       2 Dir(s) 2,557,210,624 bytes free 

C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet>javac WelcomeApplet.java 

C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet>dir 
Volume in drive C has no label. 
Volume Serial Number is 2041-64E7 

Directory of C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet 

2009-07-02 23:54    . 
2009-07-02 23:54    .. 
2009-07-02 23:54    975 WelcomeApplet$1.class 
2009-07-02 23:54    1,379 WelcomeApplet.class 
2004-09-06 14:57    582 WelcomeApplet.html 
2004-09-06 15:04    1,402 WelcomeApplet.java 
       4 File(s)   4,338 bytes 
       2 Dir(s) 2,557,202,432 bytes free 

C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet> 

這裏是Java文件的內容:

/** 
    @version 1.21 2002-06-19 
    @author Cay Horstmann 
*/ 

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.net.*; 

public class WelcomeApplet extends JApplet 
{ 
    public void init() 
    { 
     setLayout(new BorderLayout()); 

     JLabel label = new JLabel(getParameter("greeting"), SwingConstants.CENTER); 
     label.setFont(new Font("Serif", Font.BOLD, 18)); 
     add(label, BorderLayout.CENTER); 

     JPanel panel = new JPanel(); 

     JButton cayButton = new JButton("Cay Horstmann"); 
     cayButton.addActionListener(makeURLActionListener(
     "http://www.horstmann.com")); 
     panel.add(cayButton); 

     JButton garyButton = new JButton("Gary Cornell"); 
     garyButton.addActionListener(makeURLActionListener(
     "mailto:[email protected]")); 
     panel.add(garyButton); 

     add(panel, BorderLayout.SOUTH); 
    } 

    private ActionListener makeURLActionListener(final String u) 
    { 
     return new 
     ActionListener() 
     { 
      public void actionPerformed(ActionEvent event) 
      { 
       try 
       { 
        getAppletContext().showDocument(new URL(u)); 
       } 
       catch(MalformedURLException e) 
       { 
        e.printStackTrace(); 
       } 
      } 
     }; 
    } 
} 

回答

22

的$ 1你在WelcomeApplet.java文件中定義的匿名內部類。

例如編譯

public class Run { 
    public static void main(String[] args) { 
     System.out.println(new Object() { 
      public String toString() { 
       return "77"; 
      } 
     }); 
    } 
    private class innerNamed { 
    } 
} 

會導致Run.classRun$1.classRun$innerNamed.class產生

+0

但在WelcomeApplet.java文件中沒有內部類,我用文件內容更新。 – omg 2009-07-02 15:59:40

+2

是的,有。它是這樣開始的:return new ActionListener(){public void actionPerformed ... – 2009-07-02 16:05:20

+0

您的applet中有一個內部類,它是您在makeURLActionListener()中創建的ActionListener - Metod是類的內聯定義。你說新的ActionListener()後跟{...}中的類定義,其中你實現了actionPerformed方法 – jitter 2009-07-02 16:05:36

46

這些都是保持anonymous inner classes.class文件。

在您的例子WelcomeApplet.java包含一個頂層類(稱爲WelcomeApplet)和一個匿名內部類,其將被存儲在WelcomeApplet$1.class

請注意,持有匿名內部類的文件的確切名稱不是標準化的,可能會有所不同。但在實踐中,我還沒有看到任何其他方案,而不是這裏描述的方案。用於enumare also anonymous inner classes

特定價值機構:

枚舉常數的可選類體隱式地定義一個匿名類聲明(§15.9.5)延伸的立即封閉枚舉類型。

+0

我在這裏粘貼源代碼,並且沒有匿名內部類 – omg 2009-07-02 16:02:01

2

正是從這個代碼「行」:

return new 
    ActionListener() 
    { 
     public void actionPerformed(ActionEvent event) 
     { 
      try 
      { 
       getAppletContext().showDocument(new URL(u)); 
      } 
      catch(MalformedURLException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    }; 

您在聲明ActionListener你正在每一個方法被調用時的匿名內部類的一個實例的方式。

即使未調用該方法,上面的行仍會被編譯爲匿名內部類,無論如何。

1

在WelcomeApplet.java源匿名類時,將生成WelcomeApplet$1.class文件(匿名類是在方法調用makeURLActionListener通過調用new new ActionListener() {...}生成)

爲了解釋更清楚,在編譯產生的匿名類時間你有一個具體的命名類中的覆蓋部分或全部具體類(或接口)的行爲的一個實例任何時候內聯這樣的:

class HelloInternalClass { 
    public static final void main(String[] args) { 
    // print in another thread 
    new Thread(new Runnable() { 
     public void run() { 
     System.out.println("Printed from another thread"); 
     } 
    }).start(); 
    } 
} 

在上面的示例代碼,javac編譯器將生成2個類文件就像在你的例子中:HelloInternalClass.classHelloInternalClass$1.class

在這種情況下的匿名類將是的子類可運行並將編譯爲HelloInternalClass$1.class。順便提一句,如果您要從上面示例中的可運行實例中請求類名(通過調用getClass().getName()),您會發現它認爲自己爲「HelloInternalClass $ 1」。

0

創建:

public class A { 
    public static void main(String[] args) { 
     X x=new X(); 
     X x2=new X(){ 
     }; 
     Class<? extends Object>c2=x2.getClass(); 
     Class<? extends Object>s2=x2.getClass().getSuperclass(); 

     boolean b=false; 
    } 
    private static class X{  
    } 
} 

很難從代碼(new X{}()會比new X(){}更好)看看,但x2A$X一個子類的實例。這個小類是A$1