66
C:\Program Files\Java\jdk1.6.0_05\CoreJava\v1\v1ch2\WelcomeApplet>dir
 驱动器 C 中的卷没有标签。
 卷序列号为 2041-64E7

 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 个文件 1,984 字节
               2 Dir(s) 2,557,210,624 字节空闲

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
 驱动器 C 中的卷没有标签。
 卷序列号为 2041-64E7

 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 个文件 4,338 字节
               2 Dir(s) 2,557,202,432 字节空闲

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(); 
               }
            }
         };
   }
}
4

6 回答 6

69

这些是.class保存匿名内部类的文件。

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

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

an 的特定于值的主体enum 也是匿名内部类

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

于 2009-07-02T15:59:06.073 回答
31

$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.class,Run$1.class并被Run$innerNamed.class生成

于 2009-07-02T15:57:34.920 回答
6

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

另请参阅这个类似的问题和答案

于 2009-07-02T15:59:48.617 回答
4

它来自这行代码:

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

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

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

于 2009-07-02T16:06:52.520 回答
1

WelcomeApplet$1.class文件是为 WelcomeApplet.java 源中的一个匿名类生成的(匿名类是在方法调用 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.

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

于 2009-07-02T16:41:49.707 回答
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(){}),但x2它是 的子类的一个实例A$X。这个子类是A$1.

于 2017-03-21T12:35:19.633 回答