反编译工具分析枚举的原理

反编译工具: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 {
  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代码块中对其进行初始化,这不就是单例的写法吗?所以也知道枚举对象为什么是单例了

你可能感兴趣的:(反编译工具分析枚举的原理)