面試準備之Java反射

目錄

Class類常用到的有方法有

1.獲取Class對象的三種方式

2.獲取類的相關屬性

3.獲取類的公開方法和私有方法

4.獲取構造方法

5.反射的好處和壞處


在運行時通過Class對象動態獲取類信息,並且可以操作類或對象的內部屬性。反射可以動態創建對象並調用其屬性。而這種動態獲取信息以及動態調用對象方法的功能就是JAVA的反射。
反射中常用到的有Class,Field,Method,Constructor這幾個類,這些類也是將類信息封裝成相應的類

Class類常用到的有方法有



Method對象最重要的方法就是invoke,Constructor最重要的方法是newInstance
下面是對反射中比較常用的一些方法的舉例

class MondayStudyReflect{
    private String getup;

    private String wash;



    public String review;


    public String getWash() {
        return wash;
    }

    public void setWash(String wash) {
        this.wash = wash;
    }

    public String getReview() {
        return review;
    }

    public void setReview(String review) {
        this.review = review;
    }


    private String getGetup() {
        return getup;
    }

    private void setGetup(String getup) {
        this.getup = getup;
    }

    public MondayStudyReflect(){
        System.out.println("無參構造方法");
    }

    public MondayStudyReflect(String wash,String review){
        System.out.println("無參構造方法 wash:"+wash+";review:"+review);
        this.wash = wash;
        this.review = review;

    }

    public void study(String message){
        System.out.println("公共有參方法調用:"+message);
    }


    private void summary() {
        System.out.println("私有無參方法調用");
    }

}

1.獲取Class對象的三種方式
 

@Test
    public void getClassThreeMethod() throws Exception{
        Class classOne = MondayStudyReflect.class;
        MondayStudyReflect mondayStudyReflect = new MondayStudyReflect();
        Class classTwo =  mondayStudyReflect.getClass();
        Class classThree = Class.forName("com.example.findwork.reflect.MondayStudyReflect");
        if(classOne == classTwo && classTwo == classThree){
            System.out.println("三種方法獲取的class對象是同一個");

            //最後輸出結果
            //三種方法獲取的class對象是同一個
        }

    }

一般都是通過調用Class的forName方法來獲取類的Class對象,因爲這個更加靈活,我們只需要獲取到類的全限定名稱就可以了
通過對象的getClass方法獲取的話,我們已經有這個類的實例了,所以也不太需要class對象了。
 

2.獲取類的相關屬性

/**
     * 測試反射屬性的獲取
     * @throws Exception
     */
    @Test
    public void testReferectFields()throws Exception{
        Class classField = Class.forName("com.example.findwork.reflect.MondayStudyReflect");
        Field[] fieldArr = classField.getFields();
        System.out.println("獲取所有的公開的類屬性");
        for(Field field:fieldArr){
            System.out.println("屬性名:"+field.getName()+";屬性類型:"+field.getType());
        }

        Field[] fieldArrTwo = classField.getDeclaredFields();
        System.out.println("獲取所有的類屬性,包括私有屬性");
        for(Field field:fieldArrTwo){
            System.out.println("屬性名:"+field.getName()+";屬性類型:"+field.getType());
        }

        Field filedReview =  classField.getField("review");
        System.out.println("通過屬性名稱獲取公開屬性");

        System.out.println("屬性名:"+filedReview.getName()+";屬性類型:"+filedReview.getType());

        Field filedWash =  classField.getDeclaredField("wash");
        System.out.println("通過屬性名稱獲取私有屬性");

        System.out.println("屬性名:"+filedWash.getName()+";屬性類型:"+filedWash.getType());
    }

輸出結果

獲取所有的公開的類屬性
屬性名:review;屬性類型:class java.lang.String
獲取所有的類屬性,包括私有屬性
屬性名:getup;屬性類型:class java.lang.String
屬性名:wash;屬性類型:class java.lang.String
屬性名:review;屬性類型:class java.lang.String
通過屬性名稱獲取公開屬性
屬性名:review;屬性類型:class java.lang.String
通過屬性名稱獲取私有屬性
屬性名:wash;屬性類型:class java.lang.String

3.獲取類的公開方法和私有方法

/**
     * 測試反射方法的運用
     * @throws Exception
     */
    @Test
    public void testReflectMethod() throws Exception{
        Class classMethod = Class.forName("com.example.findwork.reflect.MondayStudyReflect");
        Method[] methodArr = classMethod.getMethods();
        System.out.println("===========獲取所有的公開的類方法=========");
        for(Method method:methodArr){
            System.out.print("方法名:"+method.getName()+"   ");
        }

        Object object = classMethod.newInstance();//其實是得到了MondayStudyReflect的實例,等同於 new MondayStudyReflect
        Method methodSetWash =  classMethod.getMethod("setWash",String.class);
        methodSetWash.invoke(object,"調用公開方法");
        Method methodGetWash = classMethod.getMethod("getWash");
        String wash = methodGetWash.invoke(object).toString();
        System.out.println("通過反射調用方法獲取到的參數 wash:"+wash);


        //調用私有方法
        Method methodSetGetup = classMethod.getDeclaredMethod("setGetup",String.class);
        methodSetGetup.setAccessible(true);//表示可以調用,沒有設置這一步調用私有方法是會出現問題的
        methodSetGetup.invoke(object,"調用私有方法");

        Method methodgetGetup = classMethod.getDeclaredMethod("getGetup");
        methodgetGetup.setAccessible(true);//表示可以調用,沒有設置這一步調用私有方法是會出現問題的
        String getUp = methodgetGetup.invoke(object).toString().toString();
        System.out.println("通過反射調用方法獲取到的參數 getUp:"+getUp);


    }

輸出結果

===========獲取所有的公開的類方法=========
方法名:setWash   方法名:getWash   方法名:getReview   方法名:setReview   方法名:study   方法名:wait   方法名:wait   方法名:wait   方法名:equals   方法名:toString   方法名:hashCode   方法名:getClass   方法名:notify   方法名:notifyAll   無參構造方法
通過反射調用方法獲取到的參數 wash:調用公開方法
通過反射調用方法獲取到的參數 getUp:調用私有方法

可以看到獲取公開所有方法的時候還會獲取父類Object公開的方法

4.獲取構造方法

/**
     * 測試構造方法的運用
     */
    @Test
    public void testReflectConsttruct() throws  Exception{
        Class classMethod = Class.forName("com.example.findwork.reflect.MondayStudyReflect");
        Constructor constructor = classMethod.getDeclaredConstructor();
        constructor.setAccessible(true);
        MondayStudyReflect nondayStudyReflect = (MondayStudyReflect)constructor.newInstance();


        Constructor constructorOne = classMethod.getConstructor(String.class,String.class);
        MondayStudyReflect nondayStudyReflectTwo = (MondayStudyReflect)constructorOne.newInstance("aaa","bbb");

    }

輸出結果

無參構造方法
無參構造方法 wash:aaa;review:bbb

5.反射的好處和壞處

好處:

1.解耦類與類之間的關係,讓類的調用更加靈活,向IOC的基本原理就是反射

壞處

1.調用性能沒有直接調用好

2.破壞了類的封裝性,可以調用私有方法和屬性,最典型的就是破壞了單例模式

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