在Java方法中使用标志的最佳实践

时间:2011-05-20 14:26:21

标签: java swt flags enumset

在Java方法中指定标志的最佳做法是什么?

我见过SWT使用int作为位域,比如:

(部分来自“Effective Java,2nd Ed。”第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值)混合在一起而不需要任何编译器检查。

在同一本书(“Effective Java”)中,我看到了EnumSet的使用,但随后您的用户调用变为:

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

我发现这有点冗长,我更喜欢SWT的优雅。

还有其他选择吗?或者这基本上是你必须选择的两种口味?

5 个答案:

答案 0 :(得分:7)

猜猜你已撞墙了。我没有看到任何其他选择。 Java很冗长,这是事实。在这种情况下,我通常会添加一个局部变量来使代码更具可读性。你可以这样做,

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

答案 1 :(得分:2)

如果你想要位样式标志,Java将它们包装在BitSet中。它已存在很长时间了,但很少有人愿意使用它(更喜欢在整体中嵌入C风格的位处理)。

The api for BitSet can be found here

加上一些精心选择的静态整数,在你开始检查并在一次通过中设置多个位之前,它确实很好。

答案 2 :(得分:2)

我建议您采用EnumSet方法。

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

这种方法提供了更好的类型安全性,Style作为枚举将具有完整的OO功能。

答案 3 :(得分: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));

答案 4 :(得分: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方法将数组拆分为第一个+休息块。 留给读者的练习=)