一 起源:枚举是一种特殊的数据类型,一般用来列举有限个、同类型的常量。它能保证参数的安全性,如方法声明传入的参数,必须是指定枚举中的常量。但是Android开发文档指出,使用枚举会比使用静态变量多消耗2倍内存。为什么枚举这么耗内存?
二 枚举原理:
定义枚举类 Week 星期一 到 星期五
public enum Week {MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY
}
1、使用Android Studio ReBuildProject 功能会编译成.class子节 码文件
2 在 app/build/intermediates/classes/debug/里找到生成的子节码文件为
package com.example.xu.mycustomviewdemo;public enum Week {MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY;private Week() {}
}
3、用jad反编译.class文件,生成Week.jad,jad的下载地址:http://www.javadecompilers.com/jad
jad的使用方法:jad
打开Week.jad为
package com.example.xu.mycustomviewdemo;
public final class Week extends Enum
{public static Week[] values(){return (Week[])$VALUES.clone();}public static Week valueOf(String name){return (Week)Enum.valueOf(com/example/xu/mycustomviewdemo/Week, name);}private Week(String s, int i){super(s, i);}public static final Week MONDAY;public static final Week TUESDAY;public static final Week WEDNESDAY;public static final Week THURSDAY;public static final Week FRIDAY;private static final Week $VALUES[];static {MONDAY = new Week("MONDAY", 0);TUESDAY = new Week("TUESDAY", 1);WEDNESDAY = new Week("WEDNESDAY", 2);THURSDAY = new Week("THURSDAY", 3);FRIDAY = new Week("FRIDAY", 4);$VALUES = (new Week[] {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY});}
}
从反编译的代码来看,我们定义的枚举,编译器会将其转换成一个类,这个类继承自java.lang.Enum类,除此之外,编译器还会帮我们生成多个枚举类的实例,赋值给我们定义的枚举类型常量【即static包里】,并且还声明了一个枚举对象的数组,保存了所有的枚举对象。生成的诸多对象,对象数组,远比静态变量占据内存多。
三 替代枚举的方法:
方法一 注解
1 官方提供的注解库
- compile 'com.android.support:support-annotations:24.2.0'
2 定义
@IntDef({NewWeek.MONDAY, NewWeek.TUESDAY})
@Retention(RetentionPolicy.SOURCE)
public @interface NewWeek {public static final int MONDAY = 0;public static final int TUESDAY = 1;
}
3 使用
private void setEnum(@NewWeek int week){。。}
setEnum(NewWeek.MONDAY);
方法二:接口常量
接口变量默认都是public static final
的也就是常量形式
public interface WeekInterface {int Monday = 0;int TUESDAY = 1;
}
jad 反编译子节码为:
interface WeekInterface {public static final int Monday;public static final int TUESDAY;
}
四 枚举实现单例
首先枚举里可以声明类,实例变量 和方法
enum Type{A,B,C,D;static int value;public static int getValue() {return value;}String type;public String getType() {return type;}
}
枚举定义单例:
/*** 需要被实例的类*/public class MediaManager {
}
枚举实现MediaManager单例
public enum MediaManagerCreater {// 枚举实例CREATERINSTANCE ;// 要被生名单例类的对象private MediaManager mediaManager;// 枚举构造 只生成一次MediaManagerCreater(){mediaManager = new MediaManager();}/*** 获取对应实例*/public MediaManager getManagerInstance(){return mediaManager;}
}
获取单例为:
MediaManagerCreater.CREATERINSTANCE.getManagerInstance();
原理:
1 枚举的构造函数是私有的
2 我们访问枚举实例时会执行构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次