`

产生多于的class$*.class的原因

阅读更多
   在java中,如果在一个类中定义了内部类,刚会生成:    super&this.class的文件,如果给某个控件添加了Listener事件,则会生成    super&i.class的文件,其中i为Listener的个数。  
   例如:下面的程序:  
   import    javax.swing.*;  
   import    java.awt.*;  
   import    java.awt.event.*;  
   
   
   /**  
     *    <p>Title:    </p>  
     *    <p>Description:    </p>  
     *    <p>Copyright:    Copyright    (c)    2001</p>  
     *    <p>Company:    </p>  
     *    @author    unascribed  
     *    @version    1.0  
     */  
   
   public    class    a    extends    JFrame    {  
       JPanel    jPanel1    =    new    JPanel();  
       JButton    jButton1    =    new    JButton();  
       JButton    jButton2    =    new    JButton();  
       JButton    jButton3    =    new    JButton();  
   
       public    a()    {  
           try    {  
               jbInit();  
           }  
           catch(Exception    e)    {  
               e.printStackTrace();  
           }  
       }  
       private    void    jbInit()    throws    Exception    {  
           jButton1.setText("jButton1");  
           jButton1.addActionListener(new    java.awt.event.ActionListener()    {  
               public    void    actionPerformed(ActionEvent    e)    {  
                   jButton1_actionPerformed(e);  
               }  
           });  
           jButton2.setText("jButton2");  
           jButton2.addActionListener(new    java.awt.event.ActionListener()    {  
               public    void    actionPerformed(ActionEvent    e)    {  
                   jButton2_actionPerformed(e);  
               }  
           });  
           jButton3.setText("jButton3");  
           jButton3.addActionListener(new    java.awt.event.ActionListener()    {  
               public    void    actionPerformed(ActionEvent    e)    {  
                   jButton3_actionPerformed(e);  
               }  
           });  
           this.getContentPane().add(jPanel1,    BorderLayout.CENTER);  
           jPanel1.add(jButton1,    null);  
           jPanel1.add(jButton2,    null);  
           jPanel1.add(jButton3,    null);  
       }  
   
       void    jButton1_actionPerformed(ActionEvent    e)    {  
   
       }  
   
       void    jButton2_actionPerformed(ActionEvent    e)    {  
   
       }  
   
       void    jButton3_actionPerformed(ActionEvent    e)    {  
   
       }  
       class    b{  
       }  
       class    c{  
           class    c1{}  
       }  
   }  
   编译后生成的class文件有:  
   a.class  
   a$1.class                      //jButton1.addActionListener  
   a$2.class                      //jButton2.addActionListener  
   a$3.class                      //jButton3.addActionListener  
   a$b.class  
   a$c.class  
   a$c1.class  
   但如果a.java这样定义:  
   class    a{  
   }  
   class    b{  
   }  
   注意为同一个文件:  
   刚编译后生成b.class,a.class  
   而不是a$b.class  
   
2

beyond compare来比较两种方式的编译结果,发现多出的两个类是GameClient$1.Class和GameBoard$1.Class。反编译其中的GameClient$1.Class,得到如下结果(另一个除包名外与此相同): 
// Decompiled by DJ v 2.8.8 .54 Copyright 2000 Atanas Neshkov   Date: 2005-1-24 17:22:29
// Home Page : http://members.fortunecity.com/neshkov/dj.html   - Check often for new version!
// Decompiler options: packimports(3)
// Source File Name:    GameClient.java
package xxx.xxx.xxx.xxx; (此处隐去相关信息)
static class
{
}

从这个代码来看,程序中好像有匿名类的使用,但查看程序的源代码,却找不到。那么这两个类究竟是怎么产生的呢,javac编译时究竟发生了什么呢? 

经过一番调查,终于定位了匿名类是如何产生的。让我们先来看看下面的代码: 
public class OuterClass {
     private InnerClass test = new InnerClass(); 
     private class InnerClass {
     }
}

你期望的编译结果可能是产生下面两个类文件:
OuterClass.class
OuterClass$InnerClass.class

而实际javac编译的结果类文件却是:
OuterClass.class
OuterClass$InnerClass.class
OuterClass$1.class

多出了OuterClass$1.class,这是因为:

当内部类是私有的且没有明确书写公有的构造函数时,那么缺省构造函数就是私有的,javac(SUN JDK 1.4)对这种情况的处理就是创建一个可以访问的带有一个参数的构造函数,而这个参数的类型是一个匿名的静态类,所以编译时就会多生成一个class文件。 

你可能使用Eclipse进行编译,那么是的,结果跟你期望的一致,没有OuterClass$1.class。这是为什么?Eclipse JDT使用的编译器与JDK提供的javac不一样?是的,Eclipse JDT使用的是它自己内建的编译器,有一些增强的功能,包括对上述情况的完美处理。 

终于明白了问题的根源在于,GameClient.java,GameBoard.java中分别有一个私有内部类没有定义构造函数。 

那么至此,这个问题给我们带来的启示是:
1、   确认项目最终使用的Java类的编译器。如果可能,尽可能使用javac生成结果应用程序,或是与客户达成一致。
2、   尽量明确的书写缺省构造函数及其可见性,如将上面的代码改为:
public class OuterClass {
     private InnerClass test = new InnerClass();

     private class InnerClass {
         public InnerClass() {
         }
     }
}

3 对于引用中的interface--impl

在实现类中没有缺省的构造函数,在调用的同时,就会产生额外的文件

分享到:
评论

相关推荐

    [php]mysql数据库操作——DB类

    class mysql{ private $host; // 数据库主机 private $user; // 数据库用户名 private $pass; // 数据库密码 private $data; // 数据库名 private $conn; // 数据库连接标识 private $sql; // sql语句 ...

    输出JDK和CGLib动态代理产生的class文件.zip

    本压缩文件包含两个项目,用于演示如何输出JDK和CGLib动态代理产生的class文件,欢迎下载!

    DJ Java Decompiler 3.12.12.96 老朽痴拙汉化版(JAVA反编译)

    其他的,F:/amclientsdk/**/*.class 中的两颗接连的星,表示任意层次的子目录。 在Windows资源管理器的鼠标右键菜单中你也可以立即查看到源代码。你可以在你的电脑硬盘中或者在一个网络磁盘(你有全部的访问权限...

    day019-io笔记和代码.rar

    * 产生的原因: * 1、因为字符集不统一,即编码和解码new String(b,0,read,"gbk")字符集不一致 * 2、因为字节流读取汉字的时候,字节数组长度不够,将一个汉字拆开了 * 解决: * 1. 用字符...

    PHP微信支付WxPayPubHelper

    /** * 微信支付帮助库 * ==================================================== * 接口分三种类型: * 【请求型接口】--Wxpay_client_ * 统一支付接口类--...class UnifiedOrder_pub extends Wxpay_client_...

    class design final.zip

    该案例将涵括深度学习BP神经网络,数据处理,数据产生以及Pygame,Tensorflow,Keras,Matplotlib,Pandas,numpy等库综合的使用。实现功能为利用Pygame创做扫雷机游戏,通过BP神经网络训练,使扫雷机能自主判断转向并扫雷...

    Java笔试题:Java基础概念(附答案)

    都是选择题,挺简单的: 例: 1.Java是从()语言改进重新设计。... constructor必须与class同名,但方法不能与class同名 C. constructor在一个对象被new时执行 D.一个class只能定义一个constructor 答案:C

    es6class:ES6 命令行类生成器

    es6class ES6 命令行类生成器 安装 $ npm install -g es6class 用法 es6class允许您使用命令行非常快速地生成 EcmaScript 6 类文件。 $ es6class file.js MyClass 这将使用以下代码生成一个名为file.js的 ...

    Test.class文件

    假设你的文件保持在E:/java/Test.java下面 那么你打开命令提示符,也就是 开始-&gt;...然后javac Test.java 这个是编译,编译后产生了Test.class文件 然后java Test 这个是运行,注意运行是运行main方法所在的class文件

    Java课程设计案例精编:Java课程设计案例精编.ISO

    经过编译产生*.class文件后,在C:\temp&gt;提示符下使用java –classpath . * 命令即可运行程序(其中-classpath用来告诉编译器用户类文件的路径,“ . ”表示*.class文件的路径在当前目录位置,注意点的前后均有一个...

    BarycentricCluster

    编译: $ hadoop com.sun.tools.javac.Main BC.java 这将产生几个.class文件。 将它们打包到一个名为bc.jar的.jar文件中: $ jar cf bc.jar BC * .class 要运行.jar文件,请执行以下操作: $ hadoop jar bc.jar BC ...

    页面滚动时为元素动态添加class类的jquery插件

    jquery-scrollAddclass是一款可以在页面滚动时为元素动态添加class类的jquery插件。你可以定制自己的class类,使元素在进入视口时产生指定的动画效果。

    购物网站中的购物车源代码

    /* 检查是否有 seesion, 如果没有产生一个 MD5 的唯一 id, 并利用 cookie 存入 $s 中。 并且设置其存在时间为 14400 sec 也就是 4 小时 */ $mysql_link = mysql_connect("127.0.0.1", "root", "test"); if (!...

    MASM汇编编辑器 好用 简单

    汇编语言的实现也是先利用某种编辑器编写汇编语言源程序(*.ASM),然后经过汇编得到目标模块文件(*.OBJ)、连接后形成可执行文件(*.EXE)。 1、汇编语言程序的语句格式 汇编语源程序由语句序列构成。语句一般...

    Java中Class类工作原理详解

    换言之,每当编写并且编译了一个新类,就会产生一个Class对象(恰当地说,是被保存在一个同名的.class文件中)。在运行时,当我们想生成这个类的对象时,运行这个程序的 Java虚拟机(JVM)首先检查这个类的Class对象...

    Java中的Class类

    换言之,每当编写并且编译了一个新类,就会产生一个Class对象(恰当地说,是被保存在一个同名的.class文件中)。在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机(JVM)首先检查这个类的Class对象...

    Java文档五百篇.chm

    1. Servlet的基础结构 下面我们来谈谈处理用户GET请求的最简单的servlet框架。GET请求就是用户在浏览器的地址栏里输入一个地址、在网页上...public class SomeServlet extends HttpServlet { public void doGet

    SparkStreaming_HBase:将从Kafka收集过来的数据保存到HBase中

     编写一个python工程,用于产生行为日志,每运行一次,产生所设定的数量数据,使用Linux的定时器,每隔60s执行一次,行为日志保存在文件中。使用flume对新产生的行为日志进行收集,再用Kafka进行收集、存储,使用...

    反编译器MOCHA

    首先,用WINZIP等将"mocha-b1.zip" ..."-o" 选写入已有的.mocha 文件  "ClassX.class" 指出要反编译类名  注意,不需给出输出的JAVA文件名,因为MOCHA自动产生一个与CLASS同名但扩展名为MOCHA的JAVA源文件。

    JavaSE选择题汇总.doc

    constructor必须与class同名,但方法不能与class同名 C. constructor在一个对象被new时执行 D.一个class只能定义一个constructor 答案:C 4.提供Java存取数据库能力的包是() A.java.sql B.java.awt C.java....

Global site tag (gtag.js) - Google Analytics