JavaRush /Blogue Java /Random-PT /API de reflexão. Como funciona o método getModifiers() na...
Георгий
Nível 22
Санкт-Петербург

API de reflexão. Como funciona o método getModifiers() na classe Class

Publicado no grupo Random-PT
Como um método public native int getModifiers()de uma classe Classe algumas constantes de uma classe estão relacionadas Modifier. API de reflexão.  Como funciona o método getModifiers() na Classe - 1Digamos que temos uma classe:
public static abstract class NestedClass{
}
O método getModifiers()retorna o resultado como um número no qual os modificadores de acesso da classe ou método a partir do qual ele é chamado são criptografados. Para chamar getModifiers()uma classe, por exemplo NestedClass, você precisa criar um objeto de classe Classpara a classe NestedClass. E Class<NestedClass>ligue getModifiers().
Class<NestedClass> c = NestedClass.class;
int classModifiers = c.getModifiers();
Ou em uma linha e exiba o resultado e sua representação binária:
int classModifiers = NestedClass.class.getModifiers();
System.out.printf("classModifier = %d%n",classModifiers);
System.out.printf("classModifier в двоичной системе счисления = %s%n",Integer.toBinaryString(classModifiers));
Na tela:

classModifiers = 1033
classModifiers в двоичной системе счисления = 10000001001
Ok, mas por que esse número específico? Vejamos o exemplo da classe NestedClass. Digamos que temos um método:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
}
Seus parâmetros incluirão: int allModifiers = NestedClass.class.getModifiers(), como no exemplo acima. A int specificModifierserá igual a uma das constantes de classe Modifier:, etc. (consideraremos as constantes restantes abaixo). E o método retornará para nós se a classe contiver o modificador de acesso passado para . Se não - . O código na classe de teste ficará assim: Modifier.PUBLICModifier.STATICtruespecificModifierfalse
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
Como implementar a lógica do método isModifierSet? Vamos representar modificadores na classe no sistema binário Modifier: (por exemplo, Modifier.FINAL= 0x00000010, ou no 10º sistema - 16. 16 em binário = 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 = 1.000.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
E o que vemos? Para cada modificador, um número na 10ª é obtido de forma que na 2ª, o 1 se mova uma casa para a esquerda. E getModifiers()é calculado de tal forma que se uma classe contém um determinado modificador de acesso, então o mesmo bit do modificador de acesso torna-se igual a 1. Nos NestedClassseguintes modificadores de acesso: public static abstract. Um PUBLICé igual a 0 dígito (mais à direita). B STATIC- 3. B ABSTRACT- 10. E agora olhamos para o nosso NestedClass.class.getModifiers(): Nos dígitos 0, 3 e 10 tem um! E todo o resto é zero. Em seguida, passamos a resolver o problema. Precisamos entender se nosso getModifiers()modificador específico contém. Vamos considerar o caso do modificador final. Modifier.FINAL= 16 = 0001 0000, então um é igual ao 4º dígito. Por analogia com o exemplo acima, vamos ver se o nosso NestedClass.class.getModifiers()= 100 0000 1001 Modifier.FINAL. Aqui o 4º dígito é igual a 0. Isso significa que não contém, o que é verdade ( NestedClassnot final). Mas que lógica devo escrever no método? Precisamos aplicar um valor lógico AND (&), que é 1 se ambos os bits forem 1. Caso contrário, 0. Nosso método finalmente ficará assim:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
        return (allModifiers & specificModifier) > 0;
    }
Vamos ter certeza de que o código funciona e mostrar por que funciona. Calculamos NestedClass.class.getModifiers() & Modifier.FINAL:
  • 100 0000 1001 -NestedClass.class.getModifiers()
  • 000 0001 0000 - Modifier.FINAL(adicionou 3 zeros à esquerda por conveniência)
  • 000 0000 0000 - responda 0. Não temos uma única unidade, pois apenas 1 e 1 = 1. 1 e 0 = 0, 0 e 1 = 0, 0 e 0 = 0;
Isso significa que nossa expressão returnretornará false, porque 0 > 0 - false. Isso significa que não existe tal modificador de acesso. Vamos olhar Modifier.ABSTRACT & NestedClass.class.getModifiers():
  • 100 0000 0000 -Modifier.ABSTRACT
  • 100 0000 1001 -NestedClass.class.getModifiers()
  • 100 0000 0000 – As unidades mais à esquerda correspondem. Converta para 10: a resposta é 1024.
Isso significa que nossa expressão returnretornará true, porque 1024 > 0 - true. Isso significa que existe um modificador de acesso. API de reflexão.  Como funciona o método getModifiers() na Classe - 2Da mesma forma, este método pode ser aplicado tanto a métodos de classe quanto a campos de classe. O código do campo ficará assim:
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;
    }
}
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION