W jaki sposób metoda
public native int getModifiers()
z klasy Class
i niektóre stałe z klasy są ze sobą powiązane Modifier
. Powiedzmy, że mamy klasę:
public static abstract class NestedClass{
}
Metoda getModifiers()
zwraca wynik w postaci liczby, w której zaszyfrowane są modyfikatory dostępu klasy lub metody, z której jest wywoływana. Aby wywołać getModifiers()
klasę, na przykład dla NestedClass
, musisz utworzyć obiekt klasy Class
dla tej klasy NestedClass
. I Class<NestedClass>
zadzwoń getModifiers()
.
Class<NestedClass> c = NestedClass.class;
int classModifiers = c.getModifiers();
Lub w jednym wierszu i wyświetl wynik i jego reprezentację binarną:
int classModifiers = NestedClass.class.getModifiers();
System.out.printf("classModifier = %d%n",classModifiers);
System.out.printf("classModifier в двоичной системе счисления = %s%n",Integer.toBinaryString(classModifiers));
Na ekranie:
classModifiers = 1033
classModifiers в двоичной системе счисления = 10000001001
OK, ale dlaczego akurat ten numer? Spójrzmy na przykład klasy NestedClass
. Powiedzmy, że mamy metodę:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
}
Jego parametrami będą m.in.: int allModifiers = NestedClass.class.getModifiers()
, jak w powyższym przykładzie. A int specificModifier
będzie równe jednej ze stałych klasy Modifier
: Modifier.PUBLIC
, Modifier.STATIC
itd. (pozostałe stałe rozważymy poniżej). A metoda wróci do nas, true
jeśli klasa zawiera modyfikator dostępu przekazany do specificModifier
. Jeśli nie - false
. Kod w klasie testowej będzie wyglądał następująco:
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
Jak wdrożyć logikę metody isModifierSet
? Przedstawmy modyfikatory w klasie w systemie binarnym Modifier
: (na przykład Modifier.FINAL
= 0x00000010, lub w systemie 10. - 16,16 w systemie binarnym = 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()
jest to obliczane w ten sposób, że jeśli klasa zawiera pewien modyfikator dostępu, to ten sam bit co w modyfikatorze dostępu staje się równy 1. W NestedClass
następujących modyfikatorach dostępu: public
static
abstract
. Jeden PUBLIC
jest równy 0 cyfrom (najbardziej na prawo). B STATIC
- 3. B ABSTRACT
- 10. A teraz spójrzmy na nasze NestedClass.class.getModifiers()
: W cyfrach 0, 3 i 10 ma jedną! A cała reszta to zero. Następnie przechodzimy do rozwiązania problemu. Musimy zrozumieć, czy nasz getModifiers()
konkretny modyfikator zawiera. Rozważmy przypadek modyfikatora final
. Modifier.FINAL
= 16 = 0001 0000, więc jeden jest równy czwartej cyfrze. Analogicznie do powyższego przykładu, zobaczmy, czy nasze NestedClass.class.getModifiers()
= 100 0000 1001 Modifier.FINAL
. Tutaj czwarta cyfra jest równa 0. Oznacza to, że nie zawiera, co jest prawdą ( NestedClass
nie final
). Ale jaką logikę mam napisać w metodzie? Musimy zastosować wartość logiczną AND (&)
, która wynosi 1, jeśli oba bity mają wartość 1. W przeciwnym razie 0. Nasza metoda ostatecznie będzie wyglądać następująco:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
return (allModifiers & specificModifier) > 0;
}
Upewnijmy się, że kod działa i pokażmy, dlaczego działa. Obliczamy NestedClass.class.getModifiers() & Modifier.FINAL
:
- 100 0000 1001 -
NestedClass.class.getModifiers()
- 000 0001 0000 -
Modifier.FINAL
(dla wygody dodano 3 zera po lewej stronie) - 000 0000 0000 - odpowiedź 0. Nie mamy ani jednej jednostki, bo tylko 1 i 1 = 1. 1 i 0 = 0, 0 i 1 = 0, 0 i 0 = 0;
return
zwróci false
, ponieważ 0 > 0 - false
. Oznacza to, że nie ma takiego modyfikatora dostępu. Spójrzmy Modifier.ABSTRACT & NestedClass.class.getModifiers()
:
- 100 0000 0000 -
Modifier.ABSTRACT
- 100 0000 1001 -
NestedClass.class.getModifiers()
- 100 0000 0000 — Dopasowano jednostki skrajnie lewe. Zamień na 10: odpowiedź to 1024.
return
zwróci true
, ponieważ 1024 > 0 - true
. Istnieje więc taki modyfikator dostępu. W ten sam sposób metodę tę można zastosować zarówno do metod klas, jak i pól klas. Kod pola będzie wyglądał następująco:
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