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类内部方法的一个小分析,后面有时间的话,我会再弄一份关于其实现的文章。谢谢大家,觉得我说的有什么不妥当的,也可以大胆提出,我好验证了修改。有独立见解的也欢迎说出来,撒花~~~

 

 

 

 

 

 

 

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