JavaRush /Java Blog /Random EN /reflection API. How the getModifiers() method works in th...
Георгий
Level 22
Санкт-Петербург

reflection API. How the getModifiers() method works in the Class class

Published in the Random EN group
How a method public native int getModifiers()from a class Classand some constants from a class are related Modifier. Reflection API.  How the getModifiers() method works in Class - 1Let's say we have a class:
public static abstract class NestedClass{
}
The method getModifiers()returns the result as a number in which the access modifiers of the class or method from which it is called are encrypted. To call on getModifiers()a class, for example for NestedClass, you need to create a class object Classfor the class NestedClass. And Class<NestedClass>call getModifiers().
Class<NestedClass> c = NestedClass.class;
int classModifiers = c.getModifiers();
Or in one line and display the result and its binary representation:
int classModifiers = NestedClass.class.getModifiers();
System.out.printf("classModifier = %d%n",classModifiers);
System.out.printf("classModifier в двоичной системе счисления = %s%n",Integer.toBinaryString(classModifiers));
On the screen:

classModifiers = 1033
classModifiers в двоичной системе счисления = 10000001001
Okay, but why this particular number? Let's look at the example of the class NestedClass. Let's say we have a method:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
}
Its parameters will include: int allModifiers = NestedClass.class.getModifiers(), as in the example above. A int specificModifierwill be equal to one of the class constants Modifier: Modifier.PUBLIC, Modifier.STATICetc. (we will consider the remaining constants below). And the method will return to us trueif the class contains the access modifier passed to specificModifier. If not - false. The code in the test class will look like this:
boolean isPublic = isModifierSet(classModifiers, Modifier.PUBLIC);
boolean isInterface = isModifierSet(classModifiers, Modifier.INTERFACE);
boolean isAbstract = isModifierSet(classModifiers, Modifier.ABSTRACT);

System.out.printf("\"Is NestedClass public?\" - %b%n", isPublic); //true
System.out.printf("\"Is NestedClass interface?\" - %b%n", isInterface); //false
System.out.printf("\"Is NestedClass abstract?\" - %b%n", isAbstract); //true
How to implement the logic of the method isModifierSet? Let's represent modifiers in the class in the binary system Modifier: (for example, Modifier.FINAL= 0x00000010, or in the 10th system - 16. 16 in binary = 00010000)
  • Modifier.PUBLIC = 1 = 0000 0001
  • Modifier.PRIVATE= 2 = 0000 0010
  • Modifier.PROTECTED= 4 = 0000 0100
  • Modifier.STATIC= 8 = 0000 1000
  • Modifier.FINAL= 16 = 0001 0000
  • Modifier.SYNCHRONIZED= 32 = 0010 0000
  • Modifier.VOLATILE= 64 = 0100 0000
  • Modifier.TRANSIENT= 128 = 1000 0000
  • Modifier.NATIVE= 256 = 1 0000 0000
  • Modifier.INTERFACE= 512 = 10 0000 0000
  • Modifier.ABSTRACT = 1024 = 100 0000 0000
  • NestedClass.class.getModifiers()= 1033 = 100 0000 1001
And what do we see? For each modifier, a number in the 10th is taken such that in the 2nd, their 1 moves one place to the left. And getModifiers()it is calculated in such a way that if a class contains a certain access modifier, then the same bit as in the access modifier becomes equal to 1. In NestedClassthe following access modifiers: public static abstract. One PUBLICis equal to 0 digit (farthest to the right). B STATIC- 3. B ABSTRACT- 10. And now we look at ours NestedClass.class.getModifiers(): In the 0, 3 and 10 digits it has one! And all the rest are zero. Next we move on to solving the problem. We need to understand whether our getModifiers()specific modifier contains. Let's consider the case for the modifier final. Modifier.FINAL= 16 = 0001 0000, so one is equal to the 4th digit. By analogy with the example above, let’s see if ours NestedClass.class.getModifiers()= 100 0000 1001 Modifier.FINAL. Here the 4th digit is equal to 0. This means it does not contain, which is true ( NestedClassnot final). But what logic should I write in the method? We need to apply a logical value AND (&), which is 1 if both bits are 1. Otherwise, 0. Our method will finally look like this:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
        return (allModifiers & specificModifier) > 0;
    }
Let's make sure the code works and show why it works. We calculate NestedClass.class.getModifiers() & Modifier.FINAL:
  • 100 0000 1001 -NestedClass.class.getModifiers()
  • 000 0001 0000 - Modifier.FINAL(added 3 zeros to the left for convenience)
  • 000 0000 0000 - answer 0. We don’t have a single unit, because only 1 & 1 = 1. 1 & 0 = 0, 0 & 1 = 0, 0 & 0 = 0;
This means that our expression in returnwill return false, because 0 > 0 - false. This means there is no such access modifier. Let's look Modifier.ABSTRACT & NestedClass.class.getModifiers():
  • 100 0000 0000 -Modifier.ABSTRACT
  • 100 0000 1001 -NestedClass.class.getModifiers()
  • 100 0000 0000 - The leftmost units matched. Convert to 10th: the answer is 1024.
This means that our expression in returnwill return true, because 1024 > 0 - true. So there is such an access modifier. Reflection API.  How the getModifiers() method works in Class - 2In the same way, this method can be applied to both class methods and class fields. The code for the field will look like this:
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class A {
    private static transient volatile String name = "Bob";

    public static void main(String[] args) throws NoSuchFieldException {

        Field field = A.class.getDeclaredField("name");
        int fieldModifiers = field.getModifiers();

        boolean isPublic = isModifierSet(fieldModifiers, Modifier.PUBLIC);
        boolean isFinal = isModifierSet(fieldModifiers, Modifier.FINAL);
        boolean isVolatile = isModifierSet(fieldModifiers, Modifier.VOLATILE);

        System.out.printf("\"Is A.name public?\" - %b%n", isPublic); //false
        System.out.printf("\"Is A.name final?\" - %b%n", isFinal); //false
        System.out.printf("\"Is A.name volatile?\" - %b%n", isVolatile); //true
    }
    public static boolean isModifierSet(int allModifiers, int specificModifier) {
        return (allModifiers & specificModifier) > 0;
    }
}
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION