反射:獲取Class 類的實例(四種方法)


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Class 類 
 對象照鏡子后可以得到的信息:某個類的屬性、方法和構造器、某個類到底實現了哪些接
口。對於每個類而言,JRE 都為其保留一個不變的 Class 類型的對象。一個 Class 對象包含
了特定某個結構(class/interface/enum/annotation/primitive type/void/[])的有關信息。
 Class本身也是一個類
 Class 對象只能由系統建立對象
 一個加載的類在 JVM 中只會有一個Class實例
 一個Class對象對應的是一個加載到JVM中的一個.class文件
 每個類的實例都會記得自己是由哪個 Class 實例所生成
 通過Class可以完整地得到一個類中的所有被加載的結構
 Class類是Reflection的根源,針對任何你想動態加載、運行的類,唯有先獲得相應的
Class對象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//反射之前,對於Person的操作
    @Test
    public void test1() {

        //1.創建Person類的對象
        Person p1 = new Person("Tom", 12);

        //2.通過對象,調用其內部的屬性、方法
        p1.age = 10;
        System.out.println(p1.toString());

        p1.show();

        //在Person類外部,不可以通過Person類的對象調用其內部私有結構。
        //比如:name、showNation()以及私有的構造器
    }

 

 

 

//反射之后,對於Person的操作
    @Test
    public void test2() throws Exception{
        Class clazz = Person.class;
        //1.通過反射,創建Person類的對象
        Constructor cons = clazz.getConstructor(String.class,int.class);
        Object obj = cons.newInstance("Tom", 12);
        Person p = (Person) obj;
        System.out.println(p.toString());
        //2.通過反射,調用對象指定的屬性、方法
        //調用屬性
        Field age = clazz.getDeclaredField("age");
        age.set(p,10);
        System.out.println(p.toString());

        //調用方法
        Method show = clazz.getDeclaredMethod("show");
        show.invoke(p);

        System.out.println("*******************************");

        //通過反射,可以調用Person類的私有結構的。比如:私有的構造器、方法、屬性
        //調用私有的構造器
        Constructor cons1 = clazz.getDeclaredConstructor(String.class);
        cons1.setAccessible(true);
        Person p1 = (Person) cons1.newInstance("Jerry");
        System.out.println(p1);

        //調用私有的屬性
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(p1,"HanMeimei");
        System.out.println(p1);

        //調用私有的方法
        Method showNation = clazz.getDeclaredMethod("showNation", String.class);
        showNation.setAccessible(true);
        String nation = (String) showNation.invoke(p1,"中國");//相當於String nation = p1.showNation("中國")
        System.out.println(nation);


    }

 

 

 

 

//疑問1:通過直接new的方式或反射的方式都可以調用公共的結構,開發中到底用那個?
    //建議:直接new的方式。
    //什么時候會使用:反射的方式。 反射的特征:動態性
    //疑問2:反射機制與面向對象中的封裝性是不是矛盾的?如何看待兩個技術?
    //不矛盾。

    /*
    關於java.lang.Class類的理解
    1.類的加載過程:
    程序經過javac.exe命令以后,會生成一個或多個字節碼文件(.class結尾)。
    接着我們使用java.exe命令對某個字節碼文件進行解釋運行。相當於將某個字節碼文件
    加載到內存中。此過程就稱為類的加載。加載到內存中的類,我們就稱為運行時類,此
    運行時類,就作為Class的一個實例。

    2.換句話說,Class的實例就對應着一個運行時類。
    3.加載到內存中的運行時類,會緩存一定的時間。在此時間之內,我們可以通過不同的方式
    來獲取此運行時類。
     */
    //獲取Class的實例的方式(前三種方式需要掌握)
    @Test
    public void test3() throws ClassNotFoundException {
        //方式一:調用運行時類的屬性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);
        //方式二:通過運行時類的對象,調用getClass()
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);

        //方式三:調用Class的靜態方法:forName(String classPath)
        Class clazz3 = Class.forName("com.atguigu.java.Person");
//        clazz3 = Class.forName("java.lang.String");
        System.out.println(clazz3);

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz1 == clazz3);

        //方式四:使用類的加載器:ClassLoader  (了解)
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
        System.out.println(clazz4);

        System.out.println(clazz1 == clazz4);

    }

 

 

 

 

//萬事萬物皆對象?對象.xxx,File,URL,反射,前端、數據庫操作


    //Class實例可以是哪些結構的說明:
    @Test
    public void test4(){
        Class c1 = Object.class;
        Class c2 = Comparable.class;
        Class c3 = String[].class;
        Class c4 = int[][].class;
        Class c5 = ElementType.class;
        Class c6 = Override.class;
        Class c7 = int.class;
        Class c8 = void.class;
        Class c9 = Class.class;

        int[] a = new int[10];
        int[] b = new int[100];
        Class c10 = a.getClass();
        Class c11 = b.getClass();
        // 只要數組的元素類型與維度一樣,就是同一個Class
        System.out.println(c10 == c11);

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM