Como um método
public native int getModifiers()
de uma classe Class
e algumas constantes de uma classe estão relacionadas Modifier
. Digamos 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 Class
para 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 specificModifier
será 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.PUBLIC
Modifier.STATIC
true
specificModifier
false
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 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 = 1.000.0000Modifier.NATIVE
= 256 = 1 0000 0000Modifier.INTERFACE
= 512 = 10 0000 0000Modifier.ABSTRACT
= 1024 = 100 0000 0000NestedClass.class.getModifiers()
= 1033 = 100 0000 1001
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 NestedClass
seguintes 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 ( NestedClass
not 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;
return
retornará 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.
return
retornará true
, porque 1024 > 0 - true
. Isso significa que existe um modificador de acesso. Da 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;
}
}
GO TO FULL VERSION