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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6073347/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:11:56  来源:igfitidea点击:

Best practice of using flags in Java method

javaswtflagsenumset

提问by Roalt

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

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

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

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

(example partially from "Effective Java, 2nd Ed." page 159):

(部分示例来自“Effective 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) {

  }
}

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.

..但这是不鼓励的,因为您可以将来自不同类的标志(int 值)混合在一起,而无需任何编译器检查。

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

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

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

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

我觉得这有点冗长,我更喜欢 SWT 的优雅。

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

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

采纳答案by Aravindan R

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,

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

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

回答by Edwin Buck

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).

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

The api for BitSet can be found here.

可以在此处找到 BitSet 的 api

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.

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

回答by missingfaktor

I advise that you go with the EnumSetapproach.

我建议你采用这种EnumSet方法。

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

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

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

回答by bertvanbrakel

Late answer for anyone coming across this. Here is one way to do it to reduce memory and have a nice enum like api:

任何遇到此问题的人的迟到答案。这是一种减少内存并拥有像 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));

回答by John Hart

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:

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

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:

然后你的电话非常接近无类型(int)标志路线:

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 logicalOrmethod to split your array into first + rest chunks. Left as an exercise to the reader =).

遗憾的是,没有EnumSet.of(E... )工厂,只有EnumSet.of(E first, E... more),因此您需要一个通用logicalOr方法将数组拆分为 first + rest 块。 作为练习留给读者 =)