反编译工具:http://www.javadecompilers.com/jad 使用方式请见Readme.txt,在windows下运行jad -sjava xxx.class就可以轻而易举的将class文件反编译成java文件,从而分析其具体的实现原理了。
一、枚举的原理
我们都知道
Android上不应该使用枚举,占内存,应该使用@XXXDef注解来替代
但枚举的原理是什么?你说它占内存到底占多少内存呢,如何佐证?这里用jad工具简要分析一下。
首先写个枚举类
public enum Food {
FISH,MEAT,RICE
}
从java代码里看不出什么,大家应该都知道java类编译后会产生class文件。越接近底层,本质就越能暴露出来
javac编译出Food.class文件
javac Food.java
再通过javap命令看一下class文件的内容
javap Food.class
public final class Food extends java.lang.Enum<Food> {
public static final Food FISH;
public static final Food MEAT;
public static final Food RICE;
public static Food[] values();
public static Food valueOf(java.lang.String);
static {};
}
这里大概可以看到枚举的本质,我们自定义的枚举类Food其实就是一个继承于Enum,每个枚举对象都是一个static final的类对象。
利用上面的工具jad对.class进行反编译:
jad -sjava Food.class
就可以生成对应的java文件,输出如下
public final class Food extends Enum
{
public static Food[] values()
{
return (Food[])$VALUES.clone();
}
public static Food valueOf(String s)
{
return (Food)Enum.valueOf(Food, s);
}
private Food(String s, int i)
{
super(s, i);
}
public static final Food FISH;
public static final Food MEAT;
public static final Food RICE;
private static final Food $VALUES[];
static
{
FISH = new Food("FISH", 0);
MEAT = new Food("MEAT", 1);
RICE = new Food("RICE", 2);
$VALUES = (new Food[] {
FISH, MEAT, RICE
});
}
}
最终生成了这样的类。里面维护了三个Food型的静态变量,以及一个数组,并且实现了values以及valueof方法,和直接定义三个静态INT常量相比,自然内存占用要多。
另外可以看到,构造方法为private,定义了静态变量,并且在static代码块中对其进行初始化,这不就是单例的写法吗?所以也知道枚举对象为什么是单例了