1. 程式人生 > >Java反射之如何判斷類或變數、方法的修飾符(Modifier解析)

Java反射之如何判斷類或變數、方法的修飾符(Modifier解析)

       Java針對類、成員變數、方法,有很多修飾符,例如public、private、static、final、synchronized、abstract等,這些修飾符用來控制訪問許可權或其他特性。

       本文就用成員變數(Field)來舉例說明,類以及方法的修飾符獲取與成員變數是一樣的。

先看一個類

public class MyTest

{

    public int a;

    public static int b;

    public static final int c = 0;

    private int d;

}


通過反射,可以拿到這四個變數:

public static void main(String[] args) {

       Class<?> clazz = MyTest.class;

       Field[] fields = clazz.getDeclaredFields();//獲取這個類所有的成員變數

       for(Field field : fields) {

           System.out.println(field.getName());

       }

    }


輸出:

a

b

c

d

       現在,我想知道每個變數的帶有哪些修飾符,或者是不是包含某個修飾符。

       先看下Member介面:Member表示一個類中的成員,包括成員變數、方法、構造方法三種實現,上面用到的Field就是Member的一種。

Java文件:

java.lang.reflect

介面 Member

所有已知實現類:

Constructor(構造方法), Field(成員變數), Method(方法)

Member介面有個方法:

int   getModifiers()

作為整數返回由此 Member所表示的成員或構造方法的 Java語言修飾符。

同時再看java.lang.Class類中也有同樣的一個方法:

int   getModifiers()

返回此類或介面以整數編碼的

Java語言修飾符。

       這個方法就是返回一個int型的返回值,代表類、成員變數、方法的修飾符。

public static void main(String[]args) {

       Class<?> clazz = MyTest.class;

       Field[] fields = clazz.getDeclaredFields();

       for(Field field : fields)

       {

           System.out.print(field.getName() +"->");

           System.out.println(field.getModifiers());

       }

    }


輸出:

a->1

b->9

c->25

d->2

    通過返回的int型別的值,還是很難判斷這些變數有哪些修飾符。

    在這裡,需要用到java.lang.reflect.Modifier這個類。Modifier提供了很多靜態方法。如public static String toString(int mod)就可以輸出該整數對應的所有的修飾符。public static boolean isPublic(int mod)就可以判斷該整數對應的是不是包含public修飾符。

修改上面程式碼,把返回的整數轉換通過Modifier轉換一下:

public static void main(String[] args) {

       Class<?> clazz = MyTest.class;

       Field[] fields = clazz.getDeclaredFields();

       for(Field field : fields)

       {

           System.out.print(field.getName() +"->");

        System.out.println(Modifier.toString(field.getModifiers()));

       }

    }


輸出:

a->public

b->public static

c->public static final

d->private

    通過Modifier的isPublic、isPrivate、isStatic等方法,可以判斷是否包含某些修飾符,現在如果有這麼一個需求,我需要找到僅有publicstatic兩個修飾符的變數。

    現在看下Modifier的原始碼,可以看到以下程式碼:

    public static final int PUBLIC           = 0x00000001;

    public static final int PRIVATE          =0x00000002;

    public static final int PROTECTED        = 0x00000004;

    public static final int STATIC           =0x00000008;

    public static final int FINAL            =0x00000010;

    public static final int SYNCHRONIZED     = 0x00000020;


……還有很多 此處省略一萬字

把它們轉換成二進位制,可以看出,Modifier使用一個二進位制的位來表示是否包含某個修飾符。

……

native

transient

volatile

synchronized

final

static

protected

private

public

    也就是,如果是public static,對應的整數就是二進位制的:1001,也就是9。如下圖:

……

native

transient

volatile

synchronized

final

static

protected

private

public

0

0

0

0

0

1

0

0

1

    如果是public static final就是11001,也就是25。

    現在如果想判斷是否僅有public static兩個修飾符,那麼就可以判斷是否field.getModifiers() == 9。

    另外,我們也可以看到這裡設計之精妙之處:用二進位制位來標記是否包含某個修飾符。