2010-01-01 8 views
17

Я хочу сделать что-то вроде этого:создать битовую маску разрешения в Java

public enum Permissions 
{ 
    CanBlah1, 
    CanBlah2, 
    CanBlah3 
} 

byte[] userPerm = Permissions.CanBlah1 | Permissions.CanBlah2; 

// check permssions 
// 
if(userPerm && Permissions.CanBlah1 == Permissions.CanBlah1) 
{ 
     // do something 
} 

Вы можете сделать это в Java, как это? (Я происхожу из переменного тока # фоне)

ответ

37

Вы можете легко сделать это с помощью EnumSet

import java.util.EnumSet; 

import static java.util.EnumSet.of; 
import static java.util.EnumSet.range; 
import static so.User.Permissions.CanBlah1; 
import static so.User.Permissions.CanBlah2; 
import static so.User.Permissions.CanBlah3; 

public class User { 
    public enum Permissions { 
     CanBlah1, 
     CanBlah2, 
     CanBlah3 
    } 

    public static void main(String[] args) throws Exception { 
     EnumSet<Permissions> userPerms = of(CanBlah1, CanBlah2); 
     System.out.println(userPerms.contains(CanBlah1)); //true 
     System.out.println(userPerms.contains(CanBlah2)); //true 
     System.out.println(userPerms.contains(CanBlah3)); //false 
     System.out.println(userPerms.containsAll(of(CanBlah1, CanBlah3))); //false 
     System.out.println(userPerms.containsAll(range(CanBlah1, CanBlah2))); //true 
     System.out.println(userPerms.containsAll(range(CanBlah1, CanBlah3))); //false 
    } 

} 
+7

И, конечно же, EnumSet реализуется как битмаска под капотом. – Ross

+0

Они. Он использует 'long' для 64 байтов массивов' Enums', так называемых 'JubmoSet'. –

0

Насколько я знаю побитового оператора не определен для типов перечислений

+0

Да, но 'EnumSet' имеет операции с основными наборами, например union через 'addAll()' и пересечение через 'keepAll()'. См. Также: http://en.wikipedia.org/wiki/Set_(mathematics) – trashgod

3

Хотя я бы не рекомендовал он может запросить порядковый номер() перечисления и использовать его для бит-операций. Конечно, так как вы не можете определить, что порядковое для перечисления, вы должны ввести фиктивные значения, чтобы получить порядковое право

enum Example { 
    Bogus,   --> 0 
    This,    --> 1 
    That,    --> 2 
    ThisOrThat  --> 3 
}; 

Уведомления фиктивного перечисления необходимо ввести так, что

ThisOrThat.ordinal() == This.ordinal() | That.ordinal() 
+0

баллов за показ порядкового номера, не знал об этом! – Thufir

7

Это еще один вариант, аналогичный порядковому решению, за исключением того, что вы можете использовать | и & операторы с этим:

public enum Permissions { 
    CanBlah1(1), 
    CanBlah2(2), 
    CanBlah3(4); 

    public int value; 

    Permissions(int value) { 
     this.value = value; 
    } 
    public int value() { 
     return value; 
    } 
} 

public static void main(String[] args) { 
    int userPerm = Permissions.CanBlah1.value() | Permissions.CanBlah2.value(); 
    // check permssions 
    // 
    if((userPerm & Permissions.CanBlah1.value()) == Permissions.CanBlah1.value()) 
    { 
     // do something 
    } 
} 

или:

public enum Permissions { 
     CanBlah1, 
     CanBlah2, 
     CanBlah3; 

     public int value() { 
      return 1<<ordinal(); 
     } 
    } 

    public static void main(String[] args) { 
     int userPerm = Permissions.CanBlah1.value() | Permissions.CanBlah2.value(); 
     // check permssions 
     // 
     if((userPerm & Permissions.CanBlah1.value()) == Permissions.CanBlah1.value()) 
     { 
      // do something 
     } 
    } 
2

Если вы застряли в заранее Java 7 Era (Android), вы можете попробовать следующий код:

public enum STUFF_TO_BIT_BASK { 
THIS,THAT,OTHER; 

public static int getBitMask(STUFF_TO_BIT_BASK... masks) { 
    int res = 0; 

    for (STUFF_TO_BIT_BASK cap : masks) { 
     res |= (int) Math.pow(2, cap.ordinal()); 
    } 

    return res; 
} 

public boolean is(int maskToCheck){ 
    return maskToCheck | (int) Math.pow(2, this.ordinal()); 
} 

}

Смежные вопросы