Cómo se relacionan un método
public native int getModifiers()
de una clase Class
y algunas constantes de una clase Modifier
. Digamos 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 Class
para 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 specificModifier
será igual a una de las constantes de clase Modifier
: Modifier.PUBLIC
, Modifier.STATIC
etc. (Consideraremos las constantes restantes a continuación). Y el método volverá a nosotros true
si 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 0001Modifier.PRIVATE
= 2 = 0000 0010Modifier.PROTECTED
= 4 = 0000 0100Modifier.STATIC
= 8 = 0000 1000Modifier.FINAL
= 16 = 0001 0000Modifier.SYNCHRONIZED
= 32 = 0010 0000Modifier.VOLATILE
= 64 = 0100 0000Modifier.TRANSIENT
= 128 = 1000 0000Modifier.NATIVE
= 256 = 1 0000 0000Modifier.INTERFACE
= 512 = 10 0000 0000Modifier.ABSTRACT
= 1024 = 100 0000 0000NestedClass.class.getModifiers()
= 1033 = 100 0000 1001
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 NestedClass
los siguientes modificadores de acceso: public
static
abstract
. Uno PUBLIC
es 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 ( NestedClass
no 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;
return
volverá 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.
return
regresará true
, porque 1024 > 0 - true
. Entonces existe tal modificador de acceso. De 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;
}
}
GO TO FULL VERSION