Java 按位 & 运算符多重权限

Java Bitwise & operator multiple permission

我正在开发一个 java 网络应用程序,在一个数据库中 table 我有一个类型为 number 的列。但该列用于存储多个值。 (即如下所示的权限)

  1. 无=1;
  2. 查看次数 = 2;
  3. 加 = 4;
  4. 编辑=8;
  5. 插入 = 16;
  6. 删除 = 32;
  7. 全部=64;

问题

  1. 如果该列的值为 3 --> 那么我不需要选择任何内容,查看为 许可 .
  2. 如果该列的值为 12 --> 那么我需要选择添加, 编辑。

像这样

我知道我们可以通过按位运算符来做到这一点。任何实现此目的的代码都很棒。

首先,你的权限设置真的很奇怪; "nothing" 和 "all" 被分隔值是,呃。

好吧,您可以使用枚举并依赖序数;这有点hackish,但它可以工作。示例代码:

public enum Permission
{
    NOTHING,
    VIEW,
    ADD,
    EDIT,
    INSERT,
    DELETE,
    ALL,
    ;

    private static final Set<Permission> ALL_PERMISSIONS;

    static {
        final Set<Permission> set = values();
        set.remove(NOTHING);
        set.remove(ALL);
        ALL_PERMISSIONS = Collections.unmodifiableSet(set);
    }

    private static final int NOTHING_ORDINAL = NOTHING.ordinal();
    private static final int ALL_ORDINAL = ALL.ordinal();

    public static Set<Permission> fromInt(final int value)
    {
        int mask;

        mask = 1 << NOTHING_ORDINAL;
        if (value & mask == mask)
            return Collections.emptySet();

        mask = 1 << ALL_ORDINAL;
        if (value & mask == mask)
            return ALL_PERMISSIONS;

        final Set<Permission> set = EnumSet.noneOf(Permission.class);

        for (final Permission p: ALL_PERMISSIONS) {
            mask = 1 << p.ordinal();
            if (value & mask == mask)
                set.add(p);
        }

        return Collections.unmodifiableSet(set);
    }
}

现在,为什么这样做:这是因为 Enum 值的 .ordinal() 是它在枚举中出现的索引。这里,NOTHING 的序数为 0,ALL 的序数为 6。因此,如果要将一个 int 映射到一组权限,则必须检查任何权限 p,p-设置整数中的第 bit。反过来,这意味着 i & (1 << p.ordinal()) == 1 << p.ordinal().

有关详细信息,请参阅 Enum 的 javadoc。


设计考虑:不要将 "nothing" 和 "all" 存储为可能的值。两者都可以映射为整数:

  • 0 表示没有权限:
  • 查看、添加等所有权限的所有值(基本上,因为这里您总共有 5 个权限,所以该值将是 (1 << 5) - 1)。

我认为你的意思是按位运算和二进制文字。

在您的情况下,您必须使用位掩码(固定版本,谢谢@Paul Boddington 和@Jaroslaw Pawlak):

final int MASK_NOTHING = 1;
final int MASK_VIEW = 0b10;
final int MASK_ADD = 0b100;
final int MASK_EDIT = 0b1000;
final int MASK_INSERT = 0b10000;
final int MASK_DELETE = 0b100000;
final int MASK_ALL = 0b1000000;
int column = 0; //YOUR DATA HERE

if((column & MASK_NOTHING) > 0)
{

}

if((column & MASK_VIEW) > 0)
{

}

请注意:所有可能的位标志都可以独立设置...因此要么避免一次设置多个位标志,要么处理所有这些情况

二进制文字:https://docs.oracle.com/javase/7/docs/technotes/guides/language/binary-literals.html Operators : https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

感谢大家的回复。我使用 bitand 运算符创建了一个简单的实用程序,它非常适合上述用例

问题:

1 ) getPermission(3) 将 return 什么都没有并查看。

public static ArrayList<Integer> getPermission(int day) {
    List<Integer> places = Arrays.asList(1, 2, 4, 8, 16, 32, 64);
    ArrayList<Integer> d = new ArrayList<Integer>();
    for (Integer i : places) {
        if (bitWiseAnd(day, i)) {
            d.add(i);
        }
    }
    return d;
}

public static boolean bitWiseAnd(int bitwise, int operator) {
    return (bitwise & operator) > 0;
}