Як пов'язані метод
public native int getModifiers()
із класу Class
та деякі константи із класу Modifier
. Припустимо, у нас є клас:
public static abstract class NestedClass{
}
Метод getModifiers()
повертає результат у вигляді числа, в якому зашифровані модифікатори доступу того класу або методу, у якого він викликаний. Щоб викликати getModifiers()
для класу, наприклад NestedClass
, для створення об'єкта класу Class
для класу NestedClass
. А вже на об'єкті класу Class<NestedClass>
викликати getModifiers()
.
Class<NestedClass> c = NestedClass.class;
int classModifiers = c.getModifiers();
Або в один рядок і виведемо на екран результат та його двійкове уявлення:
int classModifiers = NestedClass.class.getModifiers();
System.out.printf("classModifier = %d%n",classModifiers);
System.out.printf("classModifier в двоичной системе счисления = %s%n",Integer.toBinaryString(classModifiers));
На екрані:
classModifiers = 1033
classModifiers в двоичной системе счисления = 10000001001
Добре, але чому саме це число? Давайте розбиратися на прикладі класу NestedClass
. Допустимо, у нас є метод:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
}
У його параметри надходитимуть: int allModifiers = NestedClass.class.getModifiers()
, як із прикладу вище. А int specificModifier
дорівнюватиме якийсь із констант класу Modifier
: 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
Як же реалізувати логіку методу isModifierSet
? Представимо у двійковій системі модифікатори в класі Modifier
: (наприклад, Modifier.FINAL
= 0x00000010, або в 10-й системі - 16. 16 у двійковій = 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()
обчислюється в такий спосіб, що й клас містить певний модифікатор доступу, такий самий розряд, як й у модифікаторі доступу, стає рівним 1. У NestedClass
такі модифікатори доступа: public
static
abstract
. В PUBLIC
одиниці дорівнює 0 розряд (крайній праворуч). В STATIC
- 3. В ABSTRACT
- 10. І тепер дивимося на наш NestedClass.class.getModifiers()
: У 0, 3 та 10 розрядах у нього одиниця! А решта нуль. Далі переходимо до розв'язання задачі. Ми повинні зрозуміти, чи містить наш getModifiers()
певний модифікатор. Розглянемо випадок для модифікатора final
. Modifier.FINAL
= 16 = 0001 0000, отже одиниці дорівнює 4 розряд. За аналогією з прикладом вище, дивимося, чи містить нашNestedClass.class.getModifiers()
= 100 0000 1001 Modifier.FINAL
. Тут 4 розряд дорівнює 0. Значить не містить, що відповідає дійсності ( NestedClass
не final
). Але яку логіку писати у методі? Потрібно застосувати логічне AND (&)
, яке дорівнює 1, якщо обидва біти дорівнюють 1. В інших випадках 0. Наш метод остаточно буде виглядати так:
public static boolean isModifierSet(int allModifiers, int specificModifier) {
return (allModifiers & specificModifier) > 0;
}
Переконаємося, що код працює і покажемо, чому він працює. Обчислюємо NestedClass.class.getModifiers() & Modifier.FINAL
:
- 100 0000 1001 -
NestedClass.class.getModifiers()
- 000 0001 0000 -
Modifier.FINAL
(додали зліва 3 нуля для зручності) - 000 0000 0000 - відповідь 0. Ми не маємо жодної одиниці, т.к. тільки 1&1=1. 1&0=0, 0&1=0, 0&0=0;
return
поверне false
, т.к. 0> 0 - false
. Значить, такого модифікатора доступу немає. Дивимося Modifier.ABSTRACT & NestedClass.class.getModifiers()
:
- 100 0000 0000 -
Modifier.ABSTRACT
- 100 0000 1001 -
NestedClass.class.getModifiers()
- 100 0000 0000 - Збіглися крайні одиниці зліва. Перекладаємо в десяту: відповідь 1024.
return
поверне true
, т.к. 1024 > 0 - true
. Значить, такий модифікатор доступу є. Так само цей метод можна застосовувати і до методів класу, і до полів класу. Код для поля виглядатиме так:
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;
}
}
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ