Enum VS Constants
在项目开发中,在需要定义多个常量的开发场景(如上传文件逻辑的状态回调),会犹豫是应该使用Enum枚举还是直接定义Constants常量来处理问题。
查看 Google Developer Guide, 有提到
Avoid enumerations
A single enum can add about 1.0 to 1.4 KB of size to your app’sclasses.dex
file. These additions can quickly accumulate for complex systems or shared libraries. If possible, consider using the@IntDef
annotation and ProGuardto strip enumerations out and convert them to integers. This type conversion preserves all of the type safety benefits of enums.
避免使用枚举类型
添加一个枚举类能够添加你应用的classes.dex
文件大约1到1.4KB的大小。建议使用@IntDef
annotation。
那么到正式项目中,
- 在使用混淆的情况下添加一个枚举具体会对APK添加多大的大小?
- 假如只创立一个枚举类,添加枚举中成员的个数,对
classes.dex
的影响有多大? - 增加一个枚举类,究竟添加了哪些代码?
- 在实际开发中,究竟应不应该使用枚举类代替常量的定义?
- 对需要定义多个常量的开发场景,应该假如编写代码?
带着上面的问题,通过测试工程,逐个解答。
一、在使用混淆的情况下添加一个枚举具体添加多大的大小?
1、 通过Android Studio创立一个默认项目,解压获取classes.dex
文件,大小为1342700bytes,如下图:
原始项目大小
2、 增加一个常量类,在代码中进行引用,添加代码如下:
// 常量类public class Apple { public static final int FIRST = 1; public static final int SECOND = 2; public static final int THREE = 3; public static final int FOUR = 4; public static final int FIVE = 5;}// MainActivity.classoverride fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) Log.d("s", Apple.FIRST.toString())}
重新获取classes.dex
文件,大小为1342720bytes,如下图:
使用Constants文件大小
相对原始项目: 添加20bytes
大小,影响非常小。
3、增加一个只有一个元素的枚举类,在代码中引用,另外删除掉上面常量类代码,添加代码如下:
enum Apple { FIRST}// 引用如上面的代码,此处省略
重新获取classes.dex
文件,大小为1343128bytes,如下图:
使用Enum增加一个元素文件大小
相对原始项目: 添加428bytes
大小,是添加一个常量类添加classes.dex
文件大小的21.4
倍
结论一: 在有混淆的情况下,添加一个枚举类,classes.dex
文件大约添加0.5KB的大小。
二、假如只创立一个枚举类,添加枚举中成员的个数,对classes.dex
的影响有多大?
1、 在1.3的基础上,对Apple
枚举类中多增加几个元素,代码如下:
enum Apple { FIRST, SECOND, THREE, FOUR, FIVE,}// 引用如上面的代码,此处省略
重新获取classes.dex
文件,大小为134332bytes,如下图:
使用Enum增加5个元素文件大小
相对于只有一个元素的枚举类:添加204bytes
,平均每添加一个添加50bytes
。
结论二: 假如已经存在一个枚举类,向其中,每添加一个元素,大约添加50bytes,影响并不很大。
三、增加一个枚举类,究竟添加了哪些代码?
那么,添加一个枚举类,究竟添加了哪些元素?通过反编译APK文件,我们能够获取到其中的答案。
通过Android Studio
自带的apk compare
工具,我们可以知道,每添加一个枚举,在classes.dex
中多添加1个class,添加4个method
,那么添加了什么类,添加了哪些方法?
通过反编译,贴出关键代码如下:
.class final enum Lcom/learn/enumtest/a;.super Ljava/lang/Enum;# annotations.annotation system Ldalvik/annotation/Signature; value = { "Ljava/lang/Enum<", "Lcom/learn/enumtest/a;", ">;" }.end annotation# static fields.field public static final enum a:Lcom/learn/enumtest/a;.field public static final enum b:Lcom/learn/enumtest/a;.field public static final enum c:Lcom/learn/enumtest/a;.field public static final enum d:Lcom/learn/enumtest/a;.field public static final enum e:Lcom/learn/enumtest/a;.field private static final synthetic f:[Lcom/learn/enumtest/a;# direct methods.method static constructor <clinit>()V .locals 7 new-instance v0, Lcom/learn/enumtest/a; const-string v1, "FIRST" const/4 v2, 0x0 const-string v1, "SECOND" const/4 v3, 0x1 const-string v1, "THREE" const/4 v4, 0x2 const-string v1, "FOUR" const/4 v5, 0x3 const-string v1, "FIVE" return-void // 省略掉其中部分代码.end method.method private constructor <init>(Ljava/lang/String;I)V .locals 0 .annotation system Ldalvik/annotation/Signature; value = { "()V" } .end annotation invoke-direct {p0, p1, p2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V return-void.end method.method public static valueOf(Ljava/lang/String;)Lcom/learn/enumtest/a; .locals 1 const-class v0, Lcom/learn/enumtest/a; invoke-static {v0, p0}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; move-result-object p0 check-cast p0, Lcom/learn/enumtest/a; return-object p0.end method.method public static values()[Lcom/learn/enumtest/a; .locals 1 sget-object v0, Lcom/learn/enumtest/a;->f:[Lcom/learn/enumtest/a; invoke-virtual {v0}, [Lcom/learn/enumtest/a;->clone()Ljava/lang/Object; move-result-object v0 check-cast v0, [Lcom/learn/enumtest/a; return-object v0.end method
从反编译代码中,每添加一个枚举类,无论是单独的枚举,还是内部嵌套枚举,都会向classes.dex
文件中新添加加一个java类,类中添加两个构造函数,添加一个valueof函数,添加一个values函数
结论三: 增加一个枚举,在程序编译期,会自动添加有两个构造函数的Java类,同时生成values、valueof两个函数,方便程序的调用。
四、 在实际开发中,究竟应不应该使用枚举类代替常量的定义?
通过上述比较,我们可以得出结论,使用枚举对classes.dex
文件大小的影响,是直接定义常量的21.4倍,所以为了APK包的大小,尽力少使用枚举,除非在需要常量与资源对应的情况下。
五、 对需要定义多个常量的开发场景,应该假如编写代码?
推荐使用@intDef
,代码如下:
public class Apple { @IntDef({FIRST, SECOND, THREE, FOUR, FIVE}) public @interface State { FIRST = 0; SECOND = 1; THREE = 2; FOUR = 3; FIVE = 4; } private int mState; public void setState(@State int state) { mState = state; } @State public int getState() { return mSate; }}
@interface
注解修饰State
,不需要在写public static final int
进行修饰,@IntDef
注解定义State
都包含哪些值,假如不在取值范围内,在编译期会报红提示,防止setState
被随意设置参数的问题,代替枚举优势,同时对APK包大小的添加非常小。
枚举和常量的比较,就写到这里,假如有任何疑问,欢迎留言。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Enum VS Constants