java Class類getFields和getDeclaredFields區別

Class類

在我們的java學習跟開發的過程中,跟Class類肯定是常常打交道的的,其中最常見的使用場景估計就是反射了,但是在這裏我們常常會發現Class#getDeclaredFields()和Class#getFields()分不清,跟Class#getMethods()還有Class#getDeclaredMethods()也分不清。欸。這個就很頭疼。今天我們就來看看究竟Class#getDeclaredFields()和Class#getFields()是個聲明東西,但作爲一個三流程序員我是很懶得去記東西的,有什麼問題,我們點進去看。

好,我們現在點進去看。關於getField方法的解釋如下:

其實強調的就是個公共,所以到這裏我們可以確認,返回的是一個表示公共字段的Field對象數組。但是這裏公共的,那是否包括了從父類繼承過來的非私有方法呢?而且說公共的,是說public修飾的,還是說真的是語義上的公共,即非私有。好,我們動手寫一個類試下。

public class People {
    public String mName;
    public String mSex;
    private String mSecret = "I hava a secret but I can't tell you know";


    public String getSecret() {
        return mSecret;
    }
    private void privateMethod() {
        System.out.println("just a privateMethod");
    }
}

class Man extends People{
    private String mJob;
    public String mSkill;
    protected String mDrive;
    int mAge;

    void keepFit(){
        System.out.println(Man.class.getSimpleName()+" to keepFit");
    }
}

class ExtendTest{
    public static void main(String[] args){
        Field[] fields = Man.class.getFields();
        for (Field field:fields){
            System.out.println("this is a field from "+Man.class.getSimpleName() +" : "+field);
        }
    }
}

這裏我們有個People的類,其子類是一個Man,這裏子類繼承了父類之後,我們打印了Man類的方法。日誌如下

this is a field from Man : public java.lang.String extendtest.Man.mSkill
this is a field from Man : public java.lang.String extendtest.People.mName
this is a field from Man : public java.lang.String extendtest.People.mSex

哇,這裏我們可以看見,是包括了從父類繼承到的非私有成員變量的。但是這裏有點詭異,但不至於親媽爆炸!!!我聲明瞭一個mJob的成員變量居然看不見?那我們前面已經說了,getField方法返回一個數組,該數組的元素是這個類裏的公共字段,好,這個我能理解,能給自己一個說法,那現在我們糾結第二個問題,這個公共是什麼公共?

上面我們已經可以看到,Man類裏面已經聲明瞭一個default修飾的mAge,還有一個protected的mDrive,但這裏,完完全全沒有半點蹤影。那這裏我們是不是可以看到答案了:getFileld方法返回的是數組元素是類內public修飾符所修飾的成員,這些成員包括從父類所繼承而來的

在我們瞭解了getFields之後,回過頭來我們看getDeclaredFields的相關文檔說明,而getDeclaredFields方法的解釋如下

最後給到我們的是聲明在這個類裏面的Filed對象構成的數組,包括哪些修飾符類型的呢,public, protected,default,(package) access, and private 所修飾的,其實就差跟你說全部了,但是這裏需要注意一個點,最後給你補了個刀,我敲黑板,但繼承的不算,嘿嘿,這個就很有意思。

我們還是上面的例子,再執行一個getDeclaredFields方法

        Field[] declaredFields = Man.class.getDeclaredFields();
        for (Field field:declaredFields){
            System.out.println("this is a declaredFields from "+Man.class.getSimpleName() +" : "+field);
        }

this is a declaredFields from Man : private java.lang.String extendtest.Man.mJob
this is a declaredFields from Man : public java.lang.String extendtest.Man.mSkill
this is a declaredFields from Man : protected java.lang.String extendtest.Man.mDrive
this is a declaredFields from Man : int extendtest.Man.mAge

咦,有意思,我們聲明的都在,類裏是都有這些成員。但是這裏倒是發現了,我們從父類繼承的mName和mName確實沒有在這個範圍內,那這樣就解釋得通了。

而在Class內部,也存在對應的getMethods,和getDeclaredMethods方法,大同小異,這裏就不再贅言,還是用我們上面的類。大家看看即可。下面是代碼跟輸出結果。

        Method[] methods = Man.class.getMethods();
        for (Method method:methods){
            System.out.println("this is a methods from "+Man.class.getSimpleName() +" : "+method);
        }

        Method[] declaredMethods = Man.class.getDeclaredMethods();
        for (Method method:declaredMethods){
            System.out.println("this is a declaredMethods from "+Man.class.getSimpleName() +" : "+method);
        }

this is a methods from Man : public java.lang.String extendtest.People.getSecret()
this is a methods from Man : public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
this is a methods from Man : public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
this is a methods from Man : public final void java.lang.Object.wait() throws java.lang.InterruptedException
this is a methods from Man : public boolean java.lang.Object.equals(java.lang.Object)
this is a methods from Man : public java.lang.String java.lang.Object.toString()
this is a methods from Man : public native int java.lang.Object.hashCode()
this is a methods from Man : public final native java.lang.Class java.lang.Object.getClass()
this is a methods from Man : public final native void java.lang.Object.notify()
this is a methods from Man : public final native void java.lang.Object.notifyAll()
this is a declaredMethods from Man : void extendtest.Man.keepFit()

好的,以上就是我們對Class類內部方法的一個小分析,後面有時間的話,我會再弄一份關於其實現的文章。謝謝大家,覺得我說的有什麼不妥當的,也可以大膽提出,我好驗證了修改。有獨立見解的也歡迎說出來,撒花~~~

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章