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



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

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

(部分示例来自"Effective Java,第2版"第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的优雅。

有没有其他选择,或者这基本上是您必须选择的两种口味?

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

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

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

BitSet 的 API 可以在这里找到。

再加上一些精心挑选的静态整数,它做得很好,直到你开始一次检查和设置多个位。

我建议你采用EnumSet的方法。

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

这种方法提供了更好的类型安全性,并且Style成为枚举将具有成熟的 OO 功能。

对于遇到此问题的人来说,答案很晚。这里有一种方法可以减少内存并拥有一个像 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));

如果您只有有限数量的方法将采用一组样式(如示例中的 printText),则可以调整它们的签名以采用可变数量的 Style 参数:

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方法来将数组拆分为第一个 + rest 块。 留给读者练习=)。

相关内容

  • 没有找到相关文章

最新更新