2011-05-20 27 views
8

在Java方法中指定標誌的最佳做法是什麼?在Java方法中使用標誌的最佳實踐

我已經看到了使用SWT int值作爲位字段,如:

(例如部分從 「有效的Java,第二版」 159頁):

public class Text { 
    public static final int STYLE_BOLD = 1 << 0; // 1 
    public static final int STYLE_ITALIC = 1 << 1; // 2 

    void printText(String text, int flags) { 

    } 
} 

和你的客戶電話是這樣的:

printText("hello", Text.STYLE_BOLD | Text.STYLE_ITALIC); 

..但這種不鼓勵,你可以混合標誌從不同的類(INT值)在一起,而沒有任何編譯器檢查。

在同一本書(「有效的Java」),我看到使用EnumSet的,但那麼你的用戶呼叫變成:

printText("hello", EnumSet.of(Style.Bold, Style.ITALIC)); 

我覺得這是一個有點冗長,我更喜歡SWT的風采。

有沒有其他的選擇,或者這基本上是你必須選擇的兩種口味?

+2

我想你的意思是'STYLE_ITALIC = 1 << 1'。 – 2011-05-20 14:30:47

+4

@Victor我認爲這是位域方法常見問題的一個很好的演示! – Anonymoose 2011-05-20 14:32:34

+0

確實如此。 :) – 2011-05-20 14:33:31

回答

7

猜猜你已經撞牆了。我沒有看到任何其他選擇。 Java是冗長的,這是一個事實。在這種情況下,我通常會添加一個局部變量以使代碼更具可讀性。你可以這樣做,

EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.ITALIC); 
printText("hello", styles); 
2

如果你想有點風格的標誌,爪哇包裝他們在一個BitSet。它已經存在了很長時間,但很少有人願意使用它(更喜歡嵌入C風格的位處理)。

The api for BitSet can be found here

再加上一些精心挑選的靜態整數,直到你開始檢查和設置多個位時,它的表現相當不錯。

+0

是的,我上個學期在我的一門課的期末考試中使用了BitSet標誌。這是一個優雅的解決方案,沒有其他學生使用,我的教授真的很喜歡它。 :)我會鼓勵人們更多地使用BitSet,它似乎並沒有被大量使用。 – RestInPeace 2014-11-12 01:22:52

2

我建議你用EnumSet的方法。

EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.Italic); 

這種方法提供了更好的類型安全,並Style是一個枚舉,將有全面的面向對象的能力。

1

任何人遇到此問題的最新答案。下面是做到這一點,以減少內存,並有一個很好的枚舉像API的一種方法:

public static class MyFlag { 

    public static final MyFlag A = new MyFlag(1<<0); 
    public static final MyFlag B = new MyFlag(1<<1); 
    public static final MyFlag C = new MyFlag(1<<2); 
    public static final MyFlag ALL = A.and(B).and(C); 

    private final int flag; 

    private MyFlag(int flag){ 
     this.flag = flag; 
    } 

    public MyFlag and(MyFlag limit){ 
     return new MyFlag(flag & limit.flag); 
    } 

    public MyFlag not(MyFlag limit){ 
     return new MyFlag(flag | ~limit.flag); 
    } 

    public boolean isSet(MyFlag limit){ 
     if(limit ==null){ 
      return false; 
     } 
     return (this.flag & limit.flag) != 0; 
    } 
} 

方法:

public void doFoo(MyFlag flag){ 
    if(MyFlag.A.isSet(flag)){ 
    .... 
    } 
    if(MyFlag.C.isSet(flag)){ 
    .... 
    } 
} 

電話:

x.doFoo(MyFlag.A.and(MyFlag.C)); 
+0

這究竟如何減少內存? – Eliezer 2016-01-20 05:41:36

0

如果你只有數量有限的方法將採取一組樣式(例如printText,在您的示例中),您可以調整其簽名以獲取可變數量的樣式參數:

void printText(String text, Style... flags) { 
    EnumSet<Style> style = logicalOr(flags); // see comment below 
    ... 
} 

然後您的通話都非常接近無類型(INT)旗航:

printText("hello", Style.BOLD, Style.ITALIC); 

可悲的是,沒有EnumSet.of(E...)工廠,只是EnumSet.of(E first, E... more),所以你需要一個通用的方法logicalOr分裂你的數組放入第一個+休息塊。 作爲練習留給讀者=)