菜鳥學JAVA之——反射

反射

之前我們學到的是封裝,而反射其實就是反封裝的過程(解封)

引入

首先我們知道,Java程序運行過程和編譯出來的class是兩套東西

我們可不可以只有類沒有對象?可以

之前那我們學習的對象都是依託於類而存在的

我們可不可以只有對象沒有類?可以。想一想io傳對象,別人創建好對象傳給你,你得到了這個對象的二進制字節,可以把這個變成一個對象而存在,只是沒有這個類型而已。

定義:

所謂反射就是指,在Java程序運行時,獲得其某些對象的實際結構與類型的過程

我們可以從類型裏面獲得:方法,方法的參數,成員變量

如果想要知道這個對象真真正正歸於那個類

Human human1 = new Woman();
       System.out.println(human1.getClass().getName());

獲取某個類型的對象(模板)

類型的對象並不是說這個類型實例化一個對象出來,而是這個類型對象裏面包括了描述這個類所有的特徵(方法、屬性)

首先理解類型也是一個類,其中類型也能創建對象

對象 = Object 類型 = Class

  1. 已經有了對象,通過 對象.getClass方法獲取

    Class c = human.getClass();

  2. 已經有了類型,通過 類型.class屬性獲取

    Class m = Woman.class;

  • m和c裏面都包括了描述Woman裏的所有的動作(屬性、方法)m和c就是Woman的類模板

  • .class文件加載到內存中後,就變成了Class

Class類裏面的一些方法

  • getConstructors():獲得指向的類型的構造方法

  • getMethods():通過類型的對象拿到這個類型裏的方法**(獲得所有方法,但不能獲取私有的方法)**(通過getMethods獲得的方法是可以直接調用的,不需任何改動)

    Method[] methods = c.getMethods();//獲得所有方法,不能獲取私有的方法
    for (Method m : methods) {
                System.out.println(m.getName());
           }
    
  • getDeclaredMethods():通過類型的對象拿到這個類型裏的方法**(獲得該類裏聲明的方法,私有公有的方法都可以獲得)**

  • getMethods(“方法名”,方法名的參數集):獲得單個方法,但是有參數

    Method md = c.getMethod("foo",null);//md是c類型下的一個方法
    Method md = c.getMethod("doo",int.class);
    
  • getParameters():獲得方法的所有參數

    Method[] methods = c.getMethods();
            for (Method m : methods) {
                System.out.print(m.getName() + "(");
                Parameter[] parameters = m.getParameters();
                for(int i = 0; i < parameters.length; i++) {
                    System.out.print(parameters[i].getType().getName());
                    if(i != parameters.length - 1) {
                        System.out.print(",");
                    }
                }
                System.out.println(")");
            }
    
  • 上面的兩個方法可以拿到方法名和他的參數,這樣就可以執行這個方法了。你可能會想有必要這麼麻煩嗎,之間去那個類裏面看一眼不就完了。這裏要告訴你,這個類你根本是看不到的!

  • getFields():獲得所有屬性

  • getField(“屬性名”):獲得某個屬性,要指定屬性名

  • set(Object obj, Object value):設置某個對象的屬性的值

  • get(Object obj):獲得某個對象的某個屬性的值

    Class c = human.getClass();
    Feild field = c.getField("age");//獲得類的名爲age的屬性放在field裏
    field.get(human);//拿到human對象裏field存放的值
    field.set(human,82);//相當於把human對象裏的age屬性的值改爲82
    

反射的🐂🍻之處:可以根據一個對象獲得類信息,也可以利用這個對象獲得類信息反過來創建新的對象,調用方法。

不用new的過程創建對象

方式一(newInstance()):

注:如果構造方法有參數,就不能用這種方式創建對象。這就需要通過反射調用有參的構造方法,然後再調用newInstance

Class c = Woman.class;//通過Woman獲得了一個Class對象
Object obj = c.newInstance(); //獲得c類型的對象(Woman類型)
Class c = Woman.class;
Constructor constructor = c.getConstructor(int.class, int.class, String.class);
Object o = constructor.newInstance(1,2,"zaq");

方式二:

  • forName(String name):創建對象,參數name必須是類的類全名(通過這種方式創建對象的前提是,這個類必須在你的項目中存在)
Class c = Woman.class;
Object obj = Class.forName(c.getName());
Object obj = Class.forName("com.home.java.Woman");

Method類裏的一些方法

  • invoke(Object obj, Object… args):用某個對象obj執行某個方法(這個對象中一定要有這個方法)(通過反射調用對象的方法)
Class c = human.getClass();
Object obj = c.newInstance(); //obj是c類型的對象
Method md = c.getMethod("doo",int.class,String.class);//md是c類型下的一個方法
md.invoke(obj,56,"aaa");//obj來執行md獲得的doo方法 等同於:obj.doo(56,"aaa");
md.invoke(human,56,"aaa");//通過反射調用對象的方法,等同於:((Woman)human).doo(56,"aaa");
  • setAccessible(true):設置可訪問私有屬性、方法。外掛呀!🙀
Method method1 = c.getDeclaredMethod("hahah");//hahah是一個私有方法
        method1.setAccessible(true);//讓私有的方法可以被訪問,外掛
        method1.invoke(o,null);

比如別人給你一個類,說這個類就工具類。我要是想知道這個類具體怎麼實現的,就可以用反射來做。(jdgui也可以)

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