簡體   English   中英

Java中的字節大小枚舉

[英]Byte-size enum in Java

我有一類可能有很多實例(在移動設備上),所以我試圖最小化大小。 我的一個字段是“DrawTarget”,它指示是否忽略繪圖操作,排隊到路徑或繪制到顯示。 我希望它只占用一個字節,因為只有3個可能的值,但我還希望它是友好的代碼,所以我沒有全部硬編碼的數字。 一種想法是使用枚舉像:

public enum DrawTarget {
    Invisible,
    Path,
    Canvas
}

但是根據我的閱讀,Java枚舉不允許您指定內存布局 - 我不能請求枚舉值表示字節大小的值 - 我想枚舉值最終是整數大小的值在Java中。

所以我想可能在枚舉中創建一個隱式轉換運算符...這在Java中是否可行? 或者是我在枚舉中實現類似內容的最佳選擇:

public static DrawTarget fromValue(byte value) {
    switch (value) {
    case 0:
        return Invisible;
    case 1:
        return Path;
    default:
        return Canvas;
    }
}

然后在我想要訪問值的地方調用DrawTarget.fromValue?

或者我應該創建一個單字節類,因為顯然(從我在研究中看到的)枚舉基本上只是Java中的特殊類?

public class DrawTarget {
    public static final byte Invisible = 0;
    public static final byte Path = 1;
    public static final byte Canvas = 2;
}

但是,如果我使用最后的解決方案,如何表示枚舉實例的值? 我仍然需要一種方法來允許“=”運算符接受類的一個靜態字段......比如轉換構造函數或賦值運算符重載。

但是,我懷疑任何類對象作為引用類型,每個實例都需要多於一個字節。 真的嗎?

在Java中,enum是一個具有盡可能多的實例的類,也有值。 實例是在類(枚舉)加載時生成的。 您使用枚舉變量或枚舉屬性的每個地方實際上都使用對現有枚舉對象之一的普通引用(在初始化枚舉后永遠不會創建枚舉實例)。

這意味着枚舉引用的成本與任何其他對象引用一樣多,通常為四個字節。 這真的,真的,真的很少。

  1. 你不知道一個字節需要多少內存(真的!記住低級內存管理包含大量的填充!),因此基於此的任何“優化”都將失敗。 在給定的體系結構中,字節字段可能占用與整數字段一樣多的內存(因為它可能更快)。

  2. 如果你想寫好Java,請使用enum。 真。 使用枚舉的唯一好處是,如果你有一個完整的數組值,例如: drawTargets[] = new DrawTarget[100000];

  3. 如果你堅持微優化,只需使用普通字節並忘記枚舉; public static final byte SOMETHING = 1; 可以進行比較(並且很難進行調試)。

我已經寫了很長時間的Android程序,並且從未見過如此微觀優化得到回報。 你的情況可能是百萬分之一,但我認為不是。

此外,為了使生活更簡單為我們大家,請考慮使用Java代碼Java約定:枚舉實例和公共最后靜態字段應該是名LIKE_THIS ,屬性likeThis (不LikeThis !)。

我想枚舉值最終是Java中的整數大小的值。

不,枚舉總是Java中的 因此,如果您有一個DrawTarget類型的DrawTarget ,那么它將是一個引用 - 無論是null還是DrawTarget的三個實例之一。 (不會有更多的實例;它不像每次使用時都會創建一個新的DrawTarget實例。)

我會使用枚舉然后測量內存使用情況 - 枚舉在邏輯上是你想要的,所以采用正常的方法編寫最簡單的代碼,然后測試性能 - 而不是猜測瓶頸可能在哪里。

可能希望在序列化時將值表示為單個字節,然后在反序列化時將其轉換回枚舉,但除此之外,如果可能,我會在整個代碼中使用枚舉類型。

除非android有一些特殊的方法來處理枚舉引用,否則每個對DropTarget的引用確實會在內存中占用多個字節。 枚舉是類,枚舉實例是對象。 因此,對枚舉實例的引用與任何其他對象引用具有相同的內存。

我不會太在意它,除非你已經測量過這會引起內存問題,並且減小尺寸會產生重大影響。

你從枚舉中獲得的主要是類型安全。 如果方法將DropTarget作為參數,那么您(或同事)將無法傳遞除DropTarget (或null)的三個實例之一之外的任何內容。 如果使用字節代替,則代碼不太清楚,任何人都可以傳遞任何字節值而不是三個授權字節值。

因此,確定哪個對您最重要,並選擇您喜歡的解決方案。

您的類只包含對枚舉的引用。 每個枚舉只會創建一個實例。

除此之外,請考慮使用多態來實現繪圖行為。

如果枚舉的值是固定的,則根據其所需的繪制行為為每個對象實例化不同的子類。

如果值經常更改,則可以在對象中保留對所需繪圖策略的引用。 對於不應繪制的對象,請參閱帶有空draw()方法的對象。 等等。

枚舉是特殊數據類型,而不是class.check oracle文檔以獲取更多詳細信息。 枚舉類型是一種特殊的數據類型,它使變量成為一組預定義的常量。 變量必須等於為其預定義的值之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM