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

发布于 2024-11-09 01:29:18 字数 717 浏览 0 评论 0原文

在 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 的优雅。

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

What's the best practice for specifying flags in a Java method?

I've seen SWT using int as bitfields, like:

(example partially from "Effective Java, 2nd Ed." page 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) {

  }
}

and your client call looks like:

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

..but this is discouraged as you can mixed flags (int values) from different classes together without any compiler checks.

In the same book ("Effective Java"), I see the use of EnumSet, but then your user call becomes:

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

I find this a bit verbose and I prefer the elegance of SWT.

Is there any other alternative or is this basically the two tastes you must pick?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

〆凄凉。 2024-11-16 01:29:18

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

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

Guess you have hit a wall. I don't see any other option. Java is verbose that's a fact. In situations like this i usually add a local variable to make the code more readable. You can do this,

EnumSet<Style> styles = EnumSet.of(Style.Bold, Style.ITALIC);
printText("hello", styles);
人生百味 2024-11-16 01:29:18

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

可以在此处找到 BitSet 的 api

再加上一些精心挑选的静态整数,它的表现相当不错,直到您开始在一次传递中检查和设置多个位。

If you want bit style flags, Java wraps them in a BitSet. It's been around for ages, yet few people bother to use it (preferring embedding C style bit handling in ints).

The api for BitSet can be found here.

Coupled with a few well chosen static ints, it does pretty well until you start getting into checking and setting multiple bits in one pass.

┾廆蒐ゝ 2024-11-16 01:29:18

我建议您采用 EnumSet 方法。

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

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

I advise that you go with the EnumSet approach.

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

This approach provides better type safety, and Style being an enum will have full-blown OO capabilities.

同尘 2024-11-16 01:29:18

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

method:

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

call 这样的漂亮枚举的方法:

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

Late answer for anyone coming across this. Here is one way to do it to reduce memory and have a nice enum like 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;
    }
}

method:

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

call:

x.doFoo(MyFlag.A.and(MyFlag.C));
你列表最软的妹 2024-11-16 01:29:18

如果您只有有限数量的方法将采用一组样式(例如您的示例中的 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..更多),所以你需要一个通用的ticalOr方法将你的数组分割成第一个+其余的块。 留给读者作为练习=)

If you only have a limited number of methods that will be taking a set of styles (like printText, in your example), you can tweak their signature to take a variable number of Style params:

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

And then your calls are very close to the untyped (int) flag route:

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

Sadly, there is no EnumSet.of(E... ) factory, just EnumSet.of(E first, E... more), so you'll need a generic logicalOr method to split your array into first + rest chunks. Left as an exercise to the reader =).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文