在做内存优化时, 推荐使用注解代替枚举, 因为枚举占用的内存更高。 这是为什么呢?
编写一个最简单的枚举类, 请问问什么枚举是静态的单例? 脑子有点懵~~~
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属于非法值,即实现了限制取值范围的作用, 这种情况并不影响编译!!!
注解还可以修饰类成员参数, 限制取值范围。