Java 枚举类型原理分析为什么枚举比用静态变量多消耗两倍的内存
程序员文章站
2022-05-12 11:33:19
...
一 起源:枚举是一种特殊的数据类型,一般用来列举有限个、同类型的常量。它能保证参数的安全性,如方法声明传入的参数,必须是指定枚举中的常量。但是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类型的,也就表明只能被实例化一次