什么是1美元的类文件名?

时间:2009-07-02 15:55:41

标签: java javac anonymous-class

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:gary@thecornells.com"));
      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(); 
               }
            }
         };
   }
}

6 个答案:

答案 0 :(得分:58)

这些是包含anonymous inner classes.class个文件。

在您的示例中,WelcomeApplet.java包含一个顶级类(称为WelcomeApplet)和一个匿名内部类,它将存储在WelcomeApplet$1.class中。

请注意,包含匿名内部类的文件的确切名称不是标准化的,可能会有所不同。但在实践中,我还没有看到任何其他方案,而不是这里描述的方案。

enum are also anonymous inner classes的价值特定机构:

  

枚举常量的可选类主体隐式定义了一个匿名类声明(§15.9.5),它扩展了直接封闭的枚举类型。

答案 1 :(得分:24)

$ 1是您在WelcomeApplet.java文件中定义的匿名内部类。

e.g。编译

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

答案 2 :(得分:4)

这些是由java编译器从WelcomeApplet.java文件中的内部和静态嵌套类生成的。

另见similar question and answer

答案 3 :(得分:2)

这是来自代码的“行”:

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

每次调用该方法时,您声明ActionListener您正在创建匿名内部类的实例的方式。

即使没有调用该方法,无论如何,上述行仍会被编译成匿名内部类。

答案 4 :(得分:1)

为WelcomeApplet.java源中的匿名类生成WelcomeApplet$1.class文件(通过调用new new ActionListener() {...}在方法调用makeURLActionListener中生成匿名类)

为了更清楚地解释,只要你有一个具体命名类的实例化,就会在编译时生成匿名类,这些类会覆盖具体类(或接口)内联的部分或全部行为,如下所示:

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

此实例中的匿名类将是 Runnable 的子类,并将编译为HelloInternalClass$1.class。顺便提一下,如果您要从上面示例中的runnable实例中询问类名(通过调用getClass().getName()),您会发现它认为自己是“ HelloInternalClass $ 1 ”。

答案 5 :(得分: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