Enum VS Constants

在項目開發(fā)中,在需要定義多個常量的開發(fā)場景(如上傳文件邏輯的狀態(tài)回調(diào))贴谎,會猶豫是應(yīng)該使用Enum枚舉還是直接定義Constants常量來解決問題。

查看 Google Developer Guide, 有提到

Avoid enumerations
A single enum can add about 1.0 to 1.4 KB of size to your app's classes.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.

避免使用枚舉類型
增加一個枚舉類能夠增加你應(yīng)用的classes.dex文件大約1到1.4KB的大小季稳。建議使用 @IntDef annotation擅这。

那么到正式項目中,

  • 在使用混淆的情況下增加一個枚舉具體會對APK增加多大的大芯笆蟆仲翎?
  • 如果只創(chuàng)建一個枚舉類,增加枚舉中成員的個數(shù)铛漓,對classes.dex的影響有多大溯香?
  • 添加一個枚舉類,到底增加了哪些代碼浓恶?
  • 在實際開發(fā)中玫坛,到底應(yīng)不應(yīng)該使用枚舉類代替常量的定義?
  • 對需要定義多個常量的開發(fā)場景包晰,應(yīng)該如果編寫代碼湿镀?

帶著上面的問題,通過測試工程伐憾,一一解答勉痴。

一、在使用混淆的情況下增加一個枚舉具體增加多大的大腥蚀腿?

1、 通過Android Studio創(chuàng)建一個默認(rèn)項目扫外,解壓獲取classes.dex文件莉钙,大小為1342700bytes,如下圖:

原始項目大小

2筛谚、 添加一個常量類磁玉,在代碼中進(jìn)行引用,增加代碼如下:

// 常量類
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.class
override 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

結(jié)論一: 在有混淆的情況下,增加一個枚舉類姐刁,classes.dex文件大約增加0.5KB的大小芥牌。

二、如果只創(chuàng)建一個枚舉類聂使,增加枚舉中成員的個數(shù)壁拉,對classes.dex的影響有多大?

1岩遗、 在1.3的基礎(chǔ)上扇商,對Apple枚舉類中多添加幾個元素,代碼如下:

enum Apple {
    FIRST,
    SECOND,
    THREE,
    FOUR,
    FIVE,
}
// 引用如上面的代碼宿礁,此處省略

重新獲取classes.dex文件案铺,大小為134332bytes,如下圖:

使用Enum添加5個元素文件大小

相對于只有一個元素的枚舉類:增加204bytes梆靖,平均每增加一個增加50bytes控汉。

結(jié)論二: 如果已經(jīng)存在一個枚舉類,向其中返吻,每增加一個元素姑子,大約增加50bytes,影響并不很大测僵。

三街佑、添加一個枚舉類,到底增加了哪些代碼捍靠?

那么沐旨,增加一個枚舉類,到底增加了哪些元素榨婆?通過反編譯APK文件磁携,我們能夠獲取到其中的答案。
通過Android Studio自帶的apk compare工具良风,我們可以知道谊迄,每增加一個枚舉闷供,在classes.dex中多增加1個class,增加4個method,那么增加了什么類统诺,增加了哪些方法歪脏?
通過反編譯,貼出關(guān)鍵代碼如下:

.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

從反編譯代碼中粮呢,每增加一個枚舉類唾糯,無論是單獨(dú)的枚舉,還是內(nèi)部嵌套枚舉鬼贱,都會向classes.dex文件中新增加一個java類,類中增加兩個構(gòu)造函數(shù)香璃,增加一個valueof函數(shù)这难,增加一個values函數(shù)

結(jié)論三: 添加一個枚舉,在程序編譯期葡秒,會自動增加有兩個構(gòu)造函數(shù)的Java類姻乓,同時生成values、valueof兩個函數(shù)眯牧,方便程序的調(diào)用蹋岩。

四、 在實際開發(fā)中学少,到底應(yīng)不應(yīng)該使用枚舉類代替常量的定義剪个?

通過上述比較,我們可以得出結(jié)論版确,使用枚舉對classes.dex文件大小的影響扣囊,是直接定義常量的21.4倍,所以為了APK包的大小绒疗,盡力少使用枚舉侵歇,除非在需要常量與資源對應(yīng)的情況下。

五吓蘑、 對需要定義多個常量的開發(fā)場景惕虑,應(yīng)該如果編寫代碼?

推薦使用@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進(jìn)行修飾磨镶,@IntDef注解定義State都包含哪些值溃蔫,如果不在取值范圍內(nèi),在編譯期會報紅提醒棋嘲,防止setState被隨便設(shè)置參數(shù)的問題酒唉,代替枚舉優(yōu)勢,同時對APK包大小的增加非常小沸移。

枚舉和常量的比較痪伦,就寫到這里侄榴,如果有任何問題,歡迎留言网沾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末癞蚕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子辉哥,更是在濱河造成了極大的恐慌桦山,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件醋旦,死亡現(xiàn)場離奇詭異恒水,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)饲齐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門钉凌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捂人,你說我怎么就攤上這事御雕。” “怎么了滥搭?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵酸纲,是天一觀的道長。 經(jīng)常有香客問我瑟匆,道長闽坡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任脓诡,我火速辦了婚禮无午,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祝谚。我一直安慰自己宪迟,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布交惯。 她就那樣靜靜地躺著次泽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪席爽。 梳的紋絲不亂的頭發(fā)上意荤,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音只锻,去河邊找鬼玖像。 笑死,一個胖子當(dāng)著我的面吹牛齐饮,可吹牛的內(nèi)容都是我干的捐寥。 我是一名探鬼主播笤昨,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼握恳!你這毒婦竟也來了瞒窒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤乡洼,失蹤者是張志新(化名)和其女友劉穎崇裁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體束昵,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拔稳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锹雏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壳炎。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖逼侦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腰耙,我是刑警寧澤榛丢,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站挺庞,受9級特大地震影響晰赞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜选侨,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一掖鱼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧援制,春花似錦戏挡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至洪己,卻和暖如春妥凳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背答捕。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工逝钥, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拱镐。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓艘款,卻偏偏與公主長得像持际,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子磷箕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345