0

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

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

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

非常感谢!

4

3 回答 3

5

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

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

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

于 2013-09-05T17:27:36.573 回答
4
new TypeToken<GenericResult<City>>() {
}

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

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

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

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

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

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

于 2013-09-05T17:28:08.047 回答
2

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

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

所以你有一个TypeToken<GenericResult<City>>地方。

浏览您的代码,我们看到

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

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

于 2013-09-05T17:29:18.990 回答