为什么在编译时创建了两个类文件?

时间:2013-09-05 17:26:26

标签: java compiler-construction

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

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编译器仍会创建两个类文件:

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>>
{
}

有人可以解释为什么要创建这个课程吗? 什么时候在编译时创建多个类文件?

非常感谢!

3 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:4)

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

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

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

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

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

  

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

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

答案 2 :(得分:2)

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

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

所以你在某个地方TypeToken<GenericResult<City>>

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

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

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