【问题标题】:Why are two class files created on compiling?为什么在编译时会创建两个类文件?
【发布时间】:2013-09-05 17:26:25
【问题描述】:

我知道当一个类有一个内部类时,这个类会被编译成两个类文件。今天我有如下代码

public class GenericDeserializer {

    public static void main(String[] args) {
        String cityPageLoadJson = "{\"count\":2,\"pageLoad\":[{\"id\":4,\"name\":\"HAN\"},{\"id\":8,\"name\":\"SGN\"}]}";
        Type type = new TypeToken<GenericResult<City>>() {
        }.getType();
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        GenericResult<City> cityPageLoad = gson.fromJson(cityPageLoadJson, type);
        for (City city : cityPageLoad.getPageLoad()) {
            System.out.println(gson.toJson(city));
        }
    }

}

上面的虽然没有内部类,但是java编译器还是会创建两个class文件:

GenericDeserializer.class
GenericDeserializer$1.class

使用Java Decompiler工具,我看到了第二个的内容

package net.tuandn.training.lesson.gson;

import com.google.gson.reflect.TypeToken;
import net.tuandn.training.model.City;
import net.tuandn.training.model.GenericResult;

final class GenericDeserializer$1 extends TypeToken<GenericResult<City>>
{
}

谁能解释一下为什么要创建这个类?
编译时何时创建多个类文件?

非常感谢!

【问题讨论】:

  • 感谢所有回答!那么第二个问题呢?请让我知道所有情况!
  • 在我的回答中更新。
  • @RohitJain 对不起,我想知道还有一件事,如果类没有内部类,包括内部匿名类,是否可以在编译时生成多个生成的类文件?你了解我吗?对不起我的英语!!!
  • 不,那是不可能的。单个类只会产生一个类文件。
  • @RohitJain 这就是我需要的答案。谢谢你非常详细的回答!

标签: java compiler-construction


【解决方案1】:

由于您在以下语句中使用了anonymous 类,因此生成了两个类文件:

    TypeToken<GenericResult<City>>() {
    .....
    }

每个匿名类文件都使用与容器类相同的名称,并附加一个 $1/$2 等等。

【讨论】:

    【解决方案2】:
    new TypeToken<GenericResult<City>>() {
    }
    

    创建一个匿名内部类。匿名内部类,就像内部类被编译成单独的类文件一样。由于匿名类没有名称,这就是为什么 numbers 用于为每个此类生成唯一名称的原因。在$ 之后看到的数字是该匿名类的编号,因为它们在您的封闭类中按顺序排列。

    如果您使用更多这样的匿名类,该数字将增加1。因此对于更多匿名类,生成的类文件如下所示:

    GenericDeserializer$1.class
    GenericDeserializer$2.class
    GenericDeserializer$3.class
    GenericDeserializer$4.class
    ....
    

    然而,对于内部类,$ 之后的值是内部类的名称,正如您已经注意到的那样。

    编译时何时创建多个类文件?

    是的,这些类是在您编译顶级类时生成的。

    【讨论】:

      【解决方案3】:

      很简单,你的反编译类显示

      final class GenericDeserializer$1 extends TypeToken<GenericResult<City>>
      

      所以你在某处有一个TypeToken&lt;GenericResult&lt;City&gt;&gt;

      查看您的代码,我们看到了

      Type type = new TypeToken<GenericResult<City>>() { /* anonymous inner class */ }.getType();
      

      那里有一个匿名的内部类声明,因此它将获得自己的带有$X 后缀的类文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-24
        • 1970-01-01
        • 2011-03-12
        • 1970-01-01
        • 2015-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多