Java – How does the getModifiers() method calculate the value for multiple modifiers

java

The Java Doc for getModifiers() is as follows:

int getModifiers()

Returns the Java language modifiers for the member or constructor represented by this Member, as an integer. The Modifier class should be used to decode the modifiers in the integer.

and Java Docs also provide the list of different modifiers and their corresponding int values:

public static final int ABSTRACT 1024

public static final int FINAL 16

public static final int INTERFACE 512

public static final int NATIVE 256

public static final int PRIVATE 2

public static final int PROTECTED 4

public static final int PUBLIC 1

public static final int STATIC 8

public static final int STRICT 2048

public static final int SYNCHRONIZED 32

public static final int TRANSIENT 128

public static final int VOLATILE 64

For a single modifier it is very straightforward for getModifiers(). It simply returns the constant value corresponding to the modifier (e.g. when I declare one class as public final and call the getModifiers() it returns 17).

System.out.println("modifierValue:" + MyClass.class.getModifiers());

Output is:

17

However, I can't quite understand how it would work for multiple modifiers. Can anyone enlighten me?

Best Solution

TL;DR: It adds them together to form a bit field.

To understand this you need to understand how binary works, this is similar to decimal - lets start there:

 1    - public
 10   - static
 100  - final

So, what does 101 mean? It must be public final because there is no other way in the decimal system to make "one hundred and one" except with a single 100 and a single 1.

Now extend this to binary:

1 - public
2 - private
4 - protected
8 - static

So what does 9 mean? Well, as with the decimal system there is only one (correct) way to make 9 in binary - one 8 and one 1.

Now we use what we call a bitfield, 9 in binary is:

1001

To verify, write some code!

public static void main(String[] args) throws Exception {
    int i = 9;
    System.out.println(Integer.toBinaryString(i));
}

Now, with the decimal system we would divide by 10 repeatedly and check the right most digit (least significant). With binary this process is identical, except we divide by 2 - this is known as bit shifting.

public static void main(String[] args) throws Exception {
    int i = 9;
    System.out.println(Integer.toBinaryString(i));
    i >>= 1;
    System.out.println(Integer.toBinaryString(i));
    i >>= 1;
    System.out.println(Integer.toBinaryString(i));
    i >>= 1;
    System.out.println(Integer.toBinaryString(i));
}

Output:

1001
100
10
1

So, if I know that private is the 21 value, and we know how many bits we have, all just need to shift the right number of digits and take the modulo with 2:

public static void main(String[] args) throws Exception {
    int i = 9;
    i >>= 2;
    System.out.println(i%2);
}

Output:

0

So we basically use the 1 and 0 values that make up a number in binary to number to store booleans.

So take this example into the read world:

public static void main(String[] args) throws Exception {
    final Method method = App.class.getMethod("myMethod");
    final int modifiers = method.getModifiers();
    System.out.println(modifiers);
    System.out.println(Integer.toBinaryString(modifiers));
}

public strictfp synchronized static final void myMethod() {

}

Output:

2105
100000111001

So we can see we have:

20 = 1 - true
21 = 2 - false
22 = 4 - false
23 = 8 - true
24 = 16 - true
25 = 32 - true
27 = 64 - false
28 = 128 - false
29 = 256 - false
210 = 512 - false
211 = 1024 - false
212 = 2048 - true