为什么推荐使用注解代替枚举?

        在做内存优化时, 推荐使用注解代替枚举, 因为枚举占用的内存更高。 这是为什么呢?

编写一个最简单的枚举类, 请问问什么枚举是静态的单例? 脑子有点懵~~~

public enum Numbers {
    One,
    Two,
    Three;
}

javac编译Numbers后生成字节码, 我们想看看到底Numbers.class到底有什么。 因为字节码比较晦涩难懂, 还是想办法用jad反编译成Java吧,链接:  http://www.javadecompilers.com/jad


打开反编译生成的Numbers.java

public final class Numbers extends Enum
{

    public static Numbers[] values()
    {
        return (Numbers[])$VALUES.clone();
    }

    public static Numbers valueOf(String name)
    {
        return (Numbers)Enum.valueOf(com/brycegao/test/Numbers, name);
    }

    private Numbers(String s, int i)
    {
        super(s, i);
    }

    public static final Numbers One;
    public static final Numbers Two;
    public static final Numbers Three;
    private static final Numbers $VALUES[];

    static 
    {
        One = new Numbers("One", 0);
        Two = new Numbers("Two", 1);
        Three = new Numbers("Three", 2);
        $VALUES = (new Numbers[] {
            One, Two, Three
        });
    }
}

从上面得到如下结论:

1、枚举类是继承于java.lang.Enum的类。

2、枚举值是类对象, 且是静态常量(被static final修饰)。

3、静态代码块内实例化枚举值,由于静态代码块的语法特性,该代码块只执行一次;

4、默认值0、1、2是在编译时生成的。

5、枚举类比常量更占内存, 因为一个Java对象至少占16个字节,  而Numbers包含了3个Java对象;而使用3个整型替换的话,只占用4 * 3即12个字节。

6、枚举的构造函数是私有的, 防止new出对象。


改用注解实现, Android提供了IntDef和StringDef注解,用于编译期的类型检查。 注意: 即使类型不匹配仍然能够生产apk包, 但IDE会给出提示信息。

      套路是声明若干个数值或字符串常量后, 创建新的注解(替换枚举)限制取值范围。

public class Numbers {
    public static final int ONE = 1;
    public static final int TWO = 2;
    public static final int THREE = 3;

    public static final String STR_ONE = "ONE";
    public static final String STR_TWO = "TWO";
    public static final String STR_THREE = "THREE";

    @IntDef({ONE, TWO, THREE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface NumbersInt {

    }

    @StringDef({STR_ONE, STR_TWO, STR_THREE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface NumbersString {

    }
}
        NumbersInt注解限制取值范围为ONE、TWO、THREE, NumbersString注解限制取值范围为STR_ONE、STR_TWO、STR_THREE。



       上面代码是使用方式, 可以看出value1的参数是合法的, 而values2的参数5属于非法值,即实现了限制取值范围的作用, 这种情况并不影响编译!!!

       注解还可以修饰类成员参数, 限制取值范围。





猜你喜欢

转载自blog.csdn.net/brycegao321/article/details/79880318