JavaRush /Blog Java /Random-ES /API de reflexión. Cómo funciona el método getModifiers() ...
Георгий
Nivel 22
Санкт-Петербург

API de reflexión. Cómo funciona el método getModifiers() en la clase Class

Publicado en el grupo Random-ES
Cómo se relacionan un método public native int getModifiers()de una clase Classy algunas constantes de una clase Modifier. API de reflexión.  Cómo funciona el método getModifiers() en la Clase - 1Digamos que tenemos una clase:
public static abstract class NestedClass{
}
El método getModifiers()devuelve el resultado como un número en el que están cifrados los modificadores de acceso de la clase o método desde el que se llama. Para llamar a getModifiers()una clase, por ejemplo NestedClass, es necesario crear un objeto de clase Classpara la clase NestedClass. Y Class<NestedClass>llama getModifiers().
Class<NestedClass> c = NestedClass.class;
int classModifiers = c.getModifiers();
O en una línea y mostrar el resultado y su representación binaria:
int classModifiers = NestedClass.class.getModifiers();
System.out.printf("classModifier = %d%n",classModifiers);
System.out.printf("classModifier в двоичной системе счисления = %s%n",Integer.toBinaryString(classModifiers));
En la pantalla:

classModifiers = 1033
classModifiers в двоичной системе счисления = 10000001001
Bien, pero ¿por qué este número en particular? Veamos el ejemplo de la clase NestedClass. Digamos que tenemos un método:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
}
Sus parámetros incluirán: int allModifiers = NestedClass.class.getModifiers(), como en el ejemplo anterior. A int specificModifierserá igual a una de las constantes de clase Modifier: Modifier.PUBLIC, Modifier.STATICetc. (Consideraremos las constantes restantes a continuación). Y el método volverá a nosotros truesi la clase contiene el modificador de acceso pasado a specificModifier. Si no - false. El código en la clase de prueba se verá así:
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
¿ Cómo implementar la lógica del método isModifierSet? Representemos modificadores en la clase en el sistema binario Modifier: (por ejemplo, Modifier.FINAL= 0x00000010, o en el décimo sistema - 16. 16 en binario = 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
Y ¿qué vemos? Para cada modificador, se toma un número en el décimo para que en el segundo, su 1 se mueva un lugar hacia la izquierda. Y getModifiers()se calcula de tal manera que si una clase contiene un determinado modificador de acceso, entonces el mismo bit que en el modificador de acceso se vuelve igual a 1. En NestedClasslos siguientes modificadores de acceso: public static abstract. Uno PUBLICes igual a 0 dígitos (el más a la derecha). B STATIC- 3. B ABSTRACT- 10. Y ahora miramos el nuestro NestedClass.class.getModifiers(): ¡En los dígitos 0, 3 y 10 tiene uno! Y todo lo demás es cero. A continuación pasamos a resolver el problema. Necesitamos entender si nuestro getModifiers()modificador específico contiene. Consideremos el caso del modificador final. Modifier.FINAL= 16 = 0001 0000, entonces uno es igual al 4to dígito. Por analogía con el ejemplo anterior, veamos si el nuestro NestedClass.class.getModifiers()= 100 0000 1001 Modifier.FINAL. Aquí el cuarto dígito es igual a 0. Esto significa que no contiene, lo cual es verdadero ( NestedClassno final). ¿Pero qué lógica debería escribir en el método? Necesitamos aplicar un valor lógico AND (&), que es 1 si ambos bits son 1. De lo contrario, 0. Nuestro método finalmente se verá así:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
        return (allModifiers & specificModifier) > 0;
    }
Asegurémonos de que el código funcione y mostremos por qué funciona. Calculamos NestedClass.class.getModifiers() & Modifier.FINAL:
  • 100 0000 1001 -NestedClass.class.getModifiers()
  • 000 0001 0000 - Modifier.FINAL(se agregaron 3 ceros a la izquierda por conveniencia)
  • 000 0000 0000 - respuesta 0. No tenemos ni una sola unidad, porque sólo 1 y 1 = 1. 1 y 0 = 0, 0 y 1 = 0, 0 y 0 = 0;
Esto significa que nuestra expresión en returnvolverá false, porque 0 > 0 - false. Esto significa que no existe tal modificador de acceso. Miremos Modifier.ABSTRACT & NestedClass.class.getModifiers():
  • 100 0000 0000 -Modifier.ABSTRACT
  • 100 0000 1001 -NestedClass.class.getModifiers()
  • 100 0000 0000: las unidades más a la izquierda coinciden. Convertir al décimo: la respuesta es 1024.
Esto significa que nuestra expresión en returnregresará true, porque 1024 > 0 - true. Entonces existe tal modificador de acceso. API de reflexión.  Cómo funciona el método getModifiers() en la Clase - 2De la misma manera, este método se puede aplicar tanto a métodos de clase como a campos de clase. El código para el campo se verá así:
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;
    }
}
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION