Java反射

1、獲取類(lèi)方式

被反射的類(lèi)

public class Student {
    //---------------構(gòu)造方法-------------------
    //(默認(rèn)的構(gòu)造方法)
    Student(String str){
        System.out.println("(默認(rèn))的構(gòu)造方法 s = " + str);
    }

    //無(wú)參構(gòu)造方法
    public Student(){
        System.out.println("調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。");
    }

    //有一個(gè)參數(shù)的構(gòu)造方法
    public Student(char name){
        System.out.println("姓名:" + name);
    }

    //有多個(gè)參數(shù)的構(gòu)造方法
    public Student(String name ,int age){
        System.out.println("姓名:"+name+"年齡:"+ age);//這的執(zhí)行效率有問(wèn)題,以后解決。
    }

    //受保護(hù)的構(gòu)造方法
    protected Student(boolean n){
        System.out.println("受保護(hù)的構(gòu)造方法 n = " + n);
    }

    //私有構(gòu)造方法
    private Student(int age){
        System.out.println("私有的構(gòu)造方法   年齡:"+ age);
    }
}

調(diào)用類(lèi)

 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //第一種方式獲取Class對(duì)象
        Student stu1 = new Student();//這一new 產(chǎn)生一個(gè)Student對(duì)象,一個(gè)Class對(duì)象。
        Class stuClass = stu1.getClass();//獲取Class對(duì)象
        System.out.println(stuClass.getName());

        //第二種方式獲取Class對(duì)象
        Class stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);//判斷第一種方式獲取的Class對(duì)象和第二種方式獲取的是否是同一個(gè)

        //第三種方式獲取Class對(duì)象
        try {
            //注意此字符串必須是真實(shí)路徑,就是帶包名的類(lèi)路徑,包名.類(lèi)名
            Class stuClass3 = Class.forName("com.javareflect.demo.Student");
            System.out.println(stuClass3 == stuClass2);//判斷三種方式是否獲取的是同一個(gè)Class對(duì)象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

結(jié)果

調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。
com.javareflect.demo.Student
true
true

2、調(diào)用類(lèi)構(gòu)造方法

調(diào)用類(lèi)

 private static Class stuClass3;

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //第一種方式獲取Class對(duì)象
        Student stu1 = new Student();//這一new 產(chǎn)生一個(gè)Student對(duì)象,一個(gè)Class對(duì)象。
        Class stuClass = stu1.getClass();//獲取Class對(duì)象
        System.out.println(stuClass.getName());

        //第二種方式獲取Class對(duì)象
        Class stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);//判斷第一種方式獲取的Class對(duì)象和第二種方式獲取的是否是同一個(gè)

        //第三種方式獲取Class對(duì)象
        try {
            //注意此字符串必須是真實(shí)路徑,就是帶包名的類(lèi)路徑,包名.類(lèi)名
            stuClass3 = Class.forName("com.javareflect.demo.Student");
            System.out.println(stuClass3 == stuClass2);//判斷三種方式是否獲取的是同一個(gè)Class對(duì)象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


        //2.獲取所有公有構(gòu)造方法
        System.out.println("**********************所有公有構(gòu)造方法*********************************");
        Constructor[] conArray = stuClass3.getConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }


        System.out.println("************所有的構(gòu)造方法(包括:私有、受保護(hù)、默認(rèn)、公有)***************");
        conArray = stuClass3.getDeclaredConstructors();
        for(Constructor c : conArray){
            System.out.println(c);
        }

        System.out.println("*****************獲取公有、無(wú)參的構(gòu)造方法*******************************");
        Constructor con = stuClass3.getConstructor(null);
        //1>、因?yàn)槭菬o(wú)參的構(gòu)造方法所以類(lèi)型是一個(gè)null,不寫(xiě)也可以:這里需要的是一個(gè)參數(shù)的類(lèi)型,切記是類(lèi)型
        //2>、返回的是描述這個(gè)無(wú)參構(gòu)造函數(shù)的類(lèi)對(duì)象。

        System.out.println("con = " + con);
        //調(diào)用構(gòu)造方法
        Object obj = con.newInstance();
        //  System.out.println("obj = " + obj);
        //  Student stu = (Student)obj;

        System.out.println("******************獲取私有構(gòu)造方法,并調(diào)用*******************************");
        con = stuClass3.getDeclaredConstructor(char.class);
        System.out.println(con);
        //調(diào)用構(gòu)造方法
        con.setAccessible(true);//暴力訪問(wèn)(忽略掉訪問(wèn)修飾符)
        obj = con.newInstance('男');
    }

Log結(jié)果:

**********************所有公有構(gòu)造方法*********************************
public com.javareflect.demo.Student(java.lang.String,int)
public com.javareflect.demo.Student(char)
public com.javareflect.demo.Student()
************所有的構(gòu)造方法(包括:私有、受保護(hù)、默認(rèn)、公有)***************
private com.javareflect.demo.Student(int)
protected com.javareflect.demo.Student(boolean)
public com.javareflect.demo.Student(java.lang.String,int)
public com.javareflect.demo.Student(char)
public com.javareflect.demo.Student()
com.javareflect.demo.Student(java.lang.String)
*****************獲取公有、無(wú)參的構(gòu)造方法*******************************
con = public com.javareflect.demo.Student()
調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。
******************獲取私有構(gòu)造方法,并調(diào)用*******************************
public com.javareflect.demo.Student(char)
姓名:男

調(diào)用方法:
1.獲取構(gòu)造方法:
1).批量的方法:
public Constructor[] getConstructors():所有"公有的"構(gòu)造方法
public Constructor[] getDeclaredConstructors():獲取所有的構(gòu)造方法(包括私有、受保護(hù)、默認(rèn)、公有)
2).獲取單個(gè)的方法,并調(diào)用:
public Constructor getConstructor(Class... parameterTypes):獲取單個(gè)的"公有的"構(gòu)造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"某個(gè)構(gòu)造方法"可以是私有的,或受保護(hù)、默認(rèn)、公有;
調(diào)用構(gòu)造方法:
Constructor-->newInstance(Object... initargs)
2、newInstance是 Constructor類(lèi)的方法(管理構(gòu)造函數(shù)的類(lèi))
api的解釋為: 使用此 Constructor 對(duì)象表示的構(gòu)造方法來(lái)創(chuàng)建該構(gòu)造方法的聲明類(lèi)的新實(shí)例,并用指定的初始化參數(shù)初始化該實(shí)例。
它的返回值是T類(lèi)型,所以newInstance是創(chuàng)建了一個(gè)構(gòu)造方法的聲明類(lèi)的新實(shí)例對(duì)象。并為之調(diào)用。

2、調(diào)用類(lèi)成員字段

被調(diào)用類(lèi)

public class Student {
    //---------------構(gòu)造方法-------------------
    //(默認(rèn)的構(gòu)造方法)
    Student(String str){
        System.out.println("(默認(rèn))的構(gòu)造方法 s = " + str);
    }

    //無(wú)參構(gòu)造方法
    public Student(){
        System.out.println("調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。");
    }

    //有一個(gè)參數(shù)的構(gòu)造方法
    public Student(char name){
        System.out.println("姓名:" + name);
    }

    //有多個(gè)參數(shù)的構(gòu)造方法
    public Student(String name ,int age){
        System.out.println("姓名:"+name+"年齡:"+ age);//這的執(zhí)行效率有問(wèn)題,以后解決。
    }

    //受保護(hù)的構(gòu)造方法
    protected Student(boolean n){
        System.out.println("受保護(hù)的構(gòu)造方法 n = " + n);
    }

    //私有構(gòu)造方法
    private Student(int age){
        System.out.println("私有的構(gòu)造方法   年齡:"+ age);
    }

    //**********字段*************//
    public String name;
    protected int age;
    char sex;
    private String phoneNum;

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex
                + ", phoneNum=" + phoneNum + "]";
    }
}

調(diào)用:

 private static Class stuClass3;
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, NoSuchFieldException {
     
        //1.獲取Class對(duì)象
        stuClass3 = Class.forName("com.javareflect.demo.Student");
        //2.獲取字段
        System.out.println("************獲取所有公有的字段********************");
        Field[] fieldArray = stuClass.getFields();
        for (Field f : fieldArray) {
            System.out.println(f);
        }
        System.out.println("************獲取所有的字段(包括私有、受保護(hù)、默認(rèn)的)********************");
        fieldArray = stuClass.getDeclaredFields();
        for (Field f : fieldArray) {
            System.out.println(f);
        }
        System.out.println("*************獲取公有字段**并調(diào)用***********************************");
        Field f = stuClass.getField("name");
        System.out.println(f);
        //獲取一個(gè)對(duì)象
        Object obj2 = stuClass.getConstructor().newInstance();//產(chǎn)生Student對(duì)象--》Student stu = new Student();
        //為字段設(shè)置值
        f.set(obj2, "劉德華");//為Student對(duì)象中的name屬性賦值--》stu.name = "劉德華"
        //驗(yàn)證
        Student stu = (Student) obj2;
        System.out.println("驗(yàn)證姓名:" + stu.name);

        System.out.println("**************獲取私有字段****并調(diào)用********************************");
        f = stuClass.getDeclaredField("phoneNum");
        System.out.println(f);
        f.setAccessible(true);//暴力反射,解除私有限定
        f.set(obj2, "18888889999");
        System.out.println("驗(yàn)證電話:" + stu);
    }

Log日志:

************獲取所有公有的字段********************
public java.lang.String com.javareflect.demo.Student.name
************獲取所有的字段(包括私有、受保護(hù)、默認(rèn)的)********************
public java.lang.String com.javareflect.demo.Student.name
protected int com.javareflect.demo.Student.age
char com.javareflect.demo.Student.sex
private java.lang.String com.javareflect.demo.Student.phoneNum
*************獲取公有字段**并調(diào)用***********************************
public java.lang.String com.javareflect.demo.Student.name
調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。
驗(yàn)證姓名:劉德華
**************獲取私有字段****并調(diào)用********************************
private java.lang.String com.javareflect.demo.Student.phoneNum
驗(yàn)證電話:Student [name=劉德華, age=0, sex= , phoneNum=18888889999]

由此可見(jiàn)
調(diào)用字段時(shí):需要傳遞兩個(gè)參數(shù):
Object obj = stuClass.getConstructor().newInstance();//產(chǎn)生Student對(duì)象--》Student stu = new Student();
//為字段設(shè)置值
f.set(obj, "劉德華");//為Student對(duì)象中的name屬性賦值--》stu.name = "劉德華"
第一個(gè)參數(shù):要傳入設(shè)置的對(duì)象,第二個(gè)參數(shù):要傳入實(shí)參

3、獲取成員方法并調(diào)用

被調(diào)用類(lèi)

public class Student {
    //**************成員方法***************//
    public void show1(String s){
        System.out.println("調(diào)用了:公有的,String參數(shù)的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("調(diào)用了:受保護(hù)的,無(wú)參的show2()");
    }
    void show3(){
        System.out.println("調(diào)用了:默認(rèn)的,無(wú)參的show3()");
    }
    private String show4(int age){
        System.out.println("調(diào)用了,私有的,并且有返回值的,int參數(shù)的show4(): age = " + age);
        return "abcd";
    }
}

調(diào)用類(lèi):

public static void main(String[] args) throws Exception {
        //1.獲取Class對(duì)象
        Class stuClass = Class.forName("fanshe.method.Student");
        //2.獲取所有公有方法
        System.out.println("***************獲取所有的”公有“方法*******************");
        stuClass.getMethods();
        Method[] methodArray = stuClass.getMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        System.out.println("***************獲取所有的方法,包括私有的*******************");
        methodArray = stuClass.getDeclaredMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        System.out.println("***************獲取公有的show1()方法*******************");
                //show1的傳參是String類(lèi)型
        Method m = stuClass.getMethod("show1", String.class);
        System.out.println(m);
        //實(shí)例化一個(gè)Student對(duì)象
        Object obj = stuClass.getConstructor().newInstance();
        m.invoke(obj, "劉德華");
        
        System.out.println("***************獲取私有的show4()方法******************");
        m = stuClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);//解除私有限定
        Object result = m.invoke(obj, 20);//需要兩個(gè)參數(shù),一個(gè)是要調(diào)用的對(duì)象(獲取有反射),一個(gè)是實(shí)參
        System.out.println("返回值:" + result);
        
        
    }

Log日志輸出;

***************獲取所有的”公有“方法*******************
public java.lang.String com.javareflect.demo.Student.toString()
public void com.javareflect.demo.Student.show1(java.lang.String)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
***************獲取所有的方法,包括私有的*******************
public java.lang.String com.javareflect.demo.Student.toString()
public void com.javareflect.demo.Student.show1(java.lang.String)
private java.lang.String com.javareflect.demo.Student.show4(int)
protected void com.javareflect.demo.Student.show2()
void com.javareflect.demo.Student.show3()
***************獲取公有的show1()方法*******************
public void com.javareflect.demo.Student.show1(java.lang.String)
調(diào)用了公有、無(wú)參構(gòu)造方法執(zhí)行了。。。
調(diào)用了:公有的,String參數(shù)的show1(): s = 劉德華
***************獲取私有的show4()方法******************
private java.lang.String com.javareflect.demo.Student.show4(int)
調(diào)用了,私有的,并且有返回值的,int參數(shù)的show4(): age = 20
返回值:abcd

由此可見(jiàn):
m = stuClass.getDeclaredMethod("show4", int.class);//調(diào)用制定方法(所有包括私有的),需要傳入兩個(gè)參數(shù),第一個(gè)是調(diào)用的方法名稱(chēng),第二個(gè)是方法的形參類(lèi)型,切記是類(lèi)型。
System.out.println(m);
m.setAccessible(true);//解除私有限定
Object result = m.invoke(obj, 20);//需要兩個(gè)參數(shù),一個(gè)是要調(diào)用的對(duì)象(獲取有反射),一個(gè)是實(shí)參
System.out.println("返回值:" + result);

4、反射main方法

public static void main(String[] args) {
    System.out.println("main方法執(zhí)行了。。。");
}

調(diào)用類(lèi)

public static void main(String[] args) {
        try {
            //1、獲取Student對(duì)象的字節(jié)碼
            Class clazz = Class.forName("com.javareflect.demo.Student");
            
            //2、獲取main方法
             Method methodMain = clazz.getMethod("main", String[].class);//第一個(gè)參數(shù):方法名稱(chēng),第二個(gè)參數(shù):方法形參的類(lèi)型,
            //3、調(diào)用main方法
            // methodMain.invoke(null, new String[]{"a","b","c"});
             //第一個(gè)參數(shù),對(duì)象類(lèi)型,因?yàn)榉椒ㄊ莝tatic靜態(tài)的,所以為null可以,第二個(gè)參數(shù)是String數(shù)組,這里要注意在jdk1.4時(shí)是數(shù)組,jdk1.5之后是可變參數(shù)
             //這里拆的時(shí)候?qū)? new String[]{"a","b","c"} 拆成3個(gè)對(duì)象。。。所以需要將它強(qiáng)轉(zhuǎn)。
             methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一
            // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Log日志輸出:

main方法執(zhí)行了。。。

5、反射方法的其它使用之---通過(guò)反射越過(guò)泛型檢查

public static void main(String[] args) throws Exception{
        ArrayList<String> strList = new ArrayList<>();
        strList.add("aaa");
        strList.add("bbb");
        
    //  strList.add(100);
        //獲取ArrayList的Class對(duì)象,反向的調(diào)用add()方法,添加數(shù)據(jù)
        Class listClass = strList.getClass(); //得到 strList 對(duì)象的字節(jié)碼 對(duì)象
        //獲取add()方法
        Method m = listClass.getMethod("add", Object.class);
        //調(diào)用add()方法
        m.invoke(strList, 100);
        
        //遍歷集合
        for(Object obj : strList){
            System.out.println(obj);
        }
    }

Log輸出:

aaa
bbb
100

泛型用在編譯期,編譯過(guò)后泛型擦除(消失掉)。所以是可以通過(guò)反射越過(guò)泛型檢查的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容