反編譯工具:http://www.javadecompilers.com/jad 使用方式請(qǐng)見(jiàn)Readme.txt,在windows下運(yùn)行jad -sjava xxx.class就可以輕而易舉的將class文件反編譯成java文件,從而分析其具體的實(shí)現(xiàn)原理了。
一、枚舉的原理
我們都知道
Android上不應(yīng)該使用枚舉,占內(nèi)存,應(yīng)該使用@XXXDef注解來(lái)替代
但枚舉的原理是什么?你說(shuō)它占內(nèi)存到底占多少內(nèi)存呢,如何佐證?這里用jad工具簡(jiǎn)要分析一下。
首先寫(xiě)個(gè)枚舉類
public enum Food {
FISH,MEAT,RICE
}
從java代碼里看不出什么,大家應(yīng)該都知道java類編譯后會(huì)產(chǎn)生class文件。越接近底層,本質(zhì)就越能暴露出來(lái)
javac編譯出Food.class文件
javac Food.java
再通過(guò)javap命令看一下class文件的內(nèi)容
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 {};
}
這里大概可以看到枚舉的本質(zhì),我們自定義的枚舉類Food其實(shí)就是一個(gè)繼承于Enum,每個(gè)枚舉對(duì)象都是一個(gè)static final的類對(duì)象。
利用上面的工具jad對(duì).class進(jìn)行反編譯:
jad -sjava Food.class
就可以生成對(duì)應(yīng)的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
});
}
}
最終生成了這樣的類。里面維護(hù)了三個(gè)Food型的靜態(tài)變量,以及一個(gè)數(shù)組,并且實(shí)現(xiàn)了values以及valueof方法,和直接定義三個(gè)靜態(tài)INT常量相比,自然內(nèi)存占用要多。
另外可以看到,構(gòu)造方法為private,定義了靜態(tài)變量,并且在static代碼塊中對(duì)其進(jìn)行初始化,這不就是單例的寫(xiě)法嗎?所以也知道枚舉對(duì)象為什么是單例了