在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的优雅。
还有其他选择吗?或者这基本上是你必须选择的两种口味?
答案 0 :(得分:7)
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
方法将数组拆分为第一个+休息块。 留给读者的练习=)。