java基礎-9 反射

反射

  • 類加載器

  • 類加載

類加載的描述

當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過類的加載,類的連接,類的初始化這三個步驟來對類進行初始化。如果不出現意外情況,JVM將會連續完成這三個步驟,所以有時也把這三個步驟統稱爲類加載或者類初始化

類的加載

  1. 就是指將class文件讀入內存,併爲之創建一個 java.lang.Class 對象
  2. 任何類被使用時,系統都會爲之建立一個 java.lang.Class 對象類的連接

/*
    ClassLoader 中的兩個方法
        static ClassLoader getSystemClassLoader​():返回用於委派的系統類加載器
        ClassLoader getParent​():返回父類加載器進行委派
 */
public class Test {
    public static void main(String[] args) {
        //static ClassLoader getSystemClassLoader​():返回用於委派的系統類加載器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);  //AppClassLoader

        //ClassLoader getParent​():返回父類加載器進行委派
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent); //PlatformClassLoader

        ClassLoader c3 = parent.getParent();
        System.out.println(c3); //null
    }
}

/*
jdk.internal.loader.ClassLoaders$AppClassLoader@78308db1
jdk.internal.loader.ClassLoaders$PlatformClassLoader@2d98a335
null
*/
  • 反射

  • 反射的概述

是指在運行時去獲取一個類的變量和方法信息。然後通過獲取到的信息來創建對象,調用方法的一種機制。由於這種動態性,可以極大的增強程序的靈活性,程序不用在編譯期就完成確定,在運行期仍然可以擴展

/*
    三種方式獲取Class對象
        1:使用類的class屬性來獲取該類對應的Class對象。舉例:Student.class將會返回Student類對應的Class對象
        2:調用對象的getClass()方法,返回該對象所屬類對應的Class對象
            該方法是Object類中的方法,所有的Java對象都可以調用該方法
        3:使用Class類中的靜態方法forName(String className),該方法需要傳入字符串參數,該字符串參數的值是某個類的全路徑,也就是完整包名的路徑
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //使用類的class屬性來獲取該類對應的Class對象
        Class<Student> stuClass = Student.class;
        System.out.println(stuClass);
        Class<Student> stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);
        System.out.println("----------------------");

        //調用對象的getClass()方法,返回該對象所屬類對應的Class對象
        Student stu = new Student();
        Class<? extends Student> stuClass3 = stu.getClass();
        System.out.println(stuClass == stuClass3);
        System.out.println("----------------------");

        //使用Class類中的靜態方法forName(String className)
        Class<?> stuClass4 = Class.forName("com.Reflect.Student");
        System.out.println(stuClass == stuClass4);
    }
}

/*
class com.Reflect.Student
true
----------------------
true
----------------------
true
*/
  • 反射獲取構造方法並使用

Class類獲取構造方法對象的方法     方法分類

方法名

說明

Constructor<?>[] getConstructors()

返回所有公共構造方法對象的數組

Constructor<?>[] getDeclaredConstructors()

返回所有構造方法對象的數組

Constructor getConstructor(Class<?>... parameterTypes)

返回單個公共構造方法對象

Constructor getDeclaredConstructor(Class<?>...

parameterTypes)

返回單個構造方法對象

package com.Reflect;

public class Student {
    //成員變量:一個私有,一個默認,一個公共
    private String name;
    int age;
    public String address;

    //構造方法:一個私有,一個默認,兩個公共
    public Student() {
    }

    private Student(String name) {
        this.name = name;
    }

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成員方法:一個私有,四個公共
    private void function() {
        System.out.println("function");
    }

    public void method1() {
        System.out.println("method");
    }

    public void method2(String s) {
        System.out.println("method:" + s);
    }

    public String method3(String s, int i) {
        return s + "," + i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}



/*
    反射獲取構造方法並使用獲取對象
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //獲取Class對象
        Class<?> stuClass = Class.forName("com.Reflect.Student");

        //Constructor<?>[] getConstructors​() 返回一個包含 Constructor對象的數組, Constructor對象反映了由該 Class對象表示的類的所有公共構造函數
        Constructor<?>[] publicConstructors = stuClass.getConstructors();   //公共構造方法數組
        for (Constructor<?> stuCon : publicConstructors) System.out.println(stuCon);
        System.out.println("------------------");

        //Constructor<?>[] getDeclaredConstructors​() 返回反映由該 Class對象表示的類聲明的所有構造函數的 Constructor對象的數組
        Constructor<?>[] allConstructors = stuClass.getDeclaredConstructors();       //所有構造方法數組
        for (Constructor<?> stuCon : allConstructors) System.out.println(stuCon);
        System.out.println("------------------");

        //Constructor提供了一個類的單個構造函數的信息和訪問權限 Constructor<?> con = c.getConstructor();
        Constructor<?> stuConstructor = stuClass.getConstructor();
        //T newInstance​(Object... initargs) 使用由此 Constructor對象表示的構造函數,使用指定的初始化參數來創建和初始化構造函數的聲明類的新實例
        Object student = stuConstructor.newInstance();
        System.out.println(student);
    }
}

/*
public com.Reflect.Student(java.lang.String,int,java.lang.String)
public com.Reflect.Student()
------------------
public com.Reflect.Student(java.lang.String,int,java.lang.String)
com.Reflect.Student(java.lang.String,int)
private com.Reflect.Student(java.lang.String)
public com.Reflect.Student()
------------------
Student{name='null', age=0, address='null'}
*/

 獲取構造方法初始化對象

通過反射獲取公共的構造方法並創建對象

/*
    反射獲取構造方法並使用獲取對象
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //獲取Class對象
        Class<?> student = Class.forName("com.Reflect.Student");

        //Constructor提供了一個類的單個構造函數的信息和訪問權限 Constructor<?> con = c.getConstructor();
        //public Student(String name, int age, String address)
        Constructor<?> stuConstructor = student.getConstructor(String.class, int.class, String.class);

        //T newInstance​(Object... initargs) 由Constructor對象表示的構造函數來創建和初始化構造函數的聲明類的新實例
        Object stu = stuConstructor.newInstance("李茂貞", 25, "岐國");
        System.out.println(stu);
    }
}
/*
Student{name='李茂貞', age=25, address='岐國'}
*/

/*
    暴力反射
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //獲取Class對象
        Class<?> student = Class.forName("com.Reflect.Student");

        //Constructor 提供了一個類的單個構造函數的信息和訪問權限 Constructor<?> con = c.getConstructor();
        //反射 私有 構造方法private Student(String name)
        Constructor<?> stuConstructor = student.getDeclaredConstructor(String.class);

        //暴力反射
        //將此反射對象的accessible標誌設置爲指示的布爾值。 值爲true表示反射對象應該在使用Java語言訪問控制時抑制檢查。 值爲false表示反射對象應該在使用Java語言訪問控制時執行檢查,並在類描述中指出變體。
        //public void setAccessible​(boolean flag):值爲true,取消訪問檢查
        stuConstructor.setAccessible(true);

        //T newInstance​(Object... initargs) 由Constructor對象表示的構造函數來創建和初始化構造函數的聲明類的新實例
        Object stu = stuConstructor.newInstance("李茂貞");
        System.out.println(stu);
    }
}
/*
Student{name='李茂貞', age=0, address='null'}
*/
  • Class類獲取成員變量對象的方法

方法分類

方法名

說明

Field[] getFields()

返回所有公共成員變量對象的數組

Field[] getDeclaredFields()

返回所有成員變量對象的數組

Field getField(String name)

返回單個公共成員變量對象

Field getDeclaredField(String name)

返回單個成員變量對象

Field類用於給成員變量賦值的方法                                                                                

方法名

說明

voidset(Object obj,Object value)

obj對象的成員變量賦值爲value

/*
    反射獲取成員變量並使用
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, NoSuchMethodException {
        //獲取Class對象
        Class<?> student = Class.forName("com.Reflect.Student");

        //Field[] getFields​() 返回一個包含 Field對象的數組, Field對象反映由該 Class對象表示的類或接口的所有可訪問的公共字段
        Field[] fields1 = student.getFields();
        //Field[] getDeclaredFields​() 返回一個 Field對象的數組,反映了由該 Class對象表示的類或接口聲明的所有字段
        Field[] declaredFields = student.getDeclaredFields();
        for (Field fi : declaredFields) System.out.println(fi);
        System.out.println("----------------------------");
        //Field getField​(String name) 返回一個 Field對象,該對象反映由該 Class對象表示的類或接口的指定公共成員字段
        Field address = student.getField("address");
        //Field getDeclaredField​(String name) 返回一個 Field對象,該對象反映由該 Class對象表示的類或接口的指定聲明字段
        Field name = student.getDeclaredField("name");

        //獲取無參構造方法創建對象
        Constructor<?> stuConstructor = student.getConstructor();
        //獲取Student類對象
        Object stu = stuConstructor.newInstance();


        //Field提供有關類或接口的單個字段的信息和動態訪問
        //void set​(Object obj, Object value) 將指定的對象參數中由此 Field對象表示的字段設置爲指定的新值
        address.set(stu, "岐國");  //addressField.set(stu, "岐國"); //給stu的成員變量address賦值爲岐國
        name.setAccessible(true);
        name.set(stu, "李茂貞");  //IllegalAccessException,前面添加 name.setAccessible(true);暴力反射
        System.out.println(stu);
    }
}
/*
private java.lang.String com.Reflect.Student.name
int com.Reflect.Student.age
public java.lang.String com.Reflect.Student.address
----------------------------
Student{name='李茂貞', age=0, address='岐國'}
*/

/*
    反射獲取成員變量並使用
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, NoSuchMethodException {
        Class student = Class.forName("com.Reflect.Student");
        Constructor<?> stuConstructor = student.getConstructor();
        Object stu = stuConstructor.newInstance();

        //name = "李茂貞"
        Field name = student.getDeclaredField("name");
        name.setAccessible(true);
        name.set(stu, "李茂貞");

        //age = 25
        Field age = student.getDeclaredField("age");
        age.setAccessible(true);
        age.set(stu, 25);

        //address = "岐國"
        Field address = student.getDeclaredField("address");
        address.setAccessible(true);
        address.set(stu, "岐國");

        System.out.println(stu);
    }
}
/*
Student{name='李茂貞', age=25, address='岐國'}
*/
  • 反射獲取成員變量並使用練習

Class類獲取成員方法對象的方法     方法分類

方法名

說明

Method[] getMethods()

返回所有公共成員方法對象的數組,包括繼承的

Method[] getDeclaredMethods()

返回所有成員方法對象的數組,不包括繼承的

Method getMethod(String name, Class<?>...

parameterTypes)

返回單個公共成員方法對象

Method getDeclaredMethod(String name, Class<?>...

parameterTypes)

返回單個成員方法對象

/*
    反射獲取成員方法並使用
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //獲取Class對象
        Class student = Class.forName("com.Test.Student");

        //Method[] getMethods​() 返回一個包含 方法對象的數組, 方法對象反映由該 Class對象表示的類或接口的所有公共方法,包括由類或接口聲明的對象以及從超類和超級接口繼承的類
        //獲取本類所有父類的公共方法
        //Method[] methods1 = student.getMethods();

        //Method[] getDeclaredMethods​() 返回一個包含 方法對象的數組, 方法對象反映由 Class對象表示的類或接口的所有聲明方法,包括public,protected,default(package)訪問和私有方法,但不包括繼承方法
        Method[] declaredMethods = student.getDeclaredMethods();
        for (Method method: declaredMethods) System.out.println(method);
        System.out.println("---------------------");

        //Method getMethod​(String name, Class<?>... parameterTypes) 返回一個 方法對象,該對象反映由該 Class對象表示的類或接口的指定公共成員方法
        //Method getDeclaredMethod​(String name, Class<?>... parameterTypes) 返回一個 方法對象,它反映此表示的類或接口的指定聲明的方法 Class對象
        Method dMethod = student.getDeclaredMethod("method1");

        //獲取無參構造方法創建對象
        Constructor stuCon = student.getConstructor();
        Object stu = stuCon.newInstance();

        //在類或接口上提供有關單一方法的信息和訪問權限
        //Object invoke​(Object obj, Object... args) 在具有指定參數的指定對象上調用此 方法對象表示的基礎方法
        //Object:返回值類型
        //obj:調用方法的對象
        //args:方法需要的參數
        dMethod.invoke(stu);
    }
}

/*
public java.lang.String com.Test.Student.toString()
private void com.Test.Student.function()
public void com.Test.Student.method1()
public java.lang.String com.Test.Student.method3(java.lang.String,int)
public void com.Test.Student.method2(java.lang.String)
---------------------
method
*/

/*
     練習:通過反射實現如下操作
        Student s = new Student();
        s.method1();
        s.method2("林青霞");
        String ss = s.method3("林青霞",30);
        System.out.println(ss);
        s.function();
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //獲取Class對象
        Class student = Class.forName("com.Test.Student");

        //Student s = new Student();
        Constructor stuCon = student.getConstructor();
        Object stu = stuCon.newInstance();

        //s.method1();
        Method method1 = student.getMethod("method1");
        method1.invoke(stu);

        //s.method2("林青霞");
        Method method2 = student.getMethod("method2", String.class);
        method2.invoke(stu, "李茂貞");

//        String ss = s.method3("林青霞",30);
//        System.out.println(ss);
        Method method3 = student.getMethod("method3", String.class, int.class);
        Object rensult = method3.invoke(stu, "李茂貞", 25);
        System.out.println(rensult);
        System.out.println((String)rensult);

        //s.function();    //private void function()
//        Method m4 = c.getMethod("function"); //NoSuchMethodException: com.itheima_02.Student.function()
        Method function = student.getDeclaredMethod("function");
        function.setAccessible(true);
        function.invoke(stu);
    }
}

/*
method
method:李茂貞
李茂貞,25
李茂貞,25
function
*/
  • 反射練習之越過泛型檢查

/*
    練習1:我有一個ArrayList<Integer>集合,現在我想在這個集合中添加一個字符串數據,如何實現?
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //創建集合
        ArrayList<Integer> array = new ArrayList<>();

        array.add(10);
        array.add(50);
        array.add(90);

        System.out.println(array);

        //獲取Classd對象
        Class<? extends ArrayList> arrayClass = array.getClass();
        Method add = arrayClass.getDeclaredMethod("add", Object.class);
        
        add.invoke(array, "hello");
        add.invoke(array, "reflect");
        
        System.out.println(array);
    }
}

/*
[10, 50, 90]
[10, 50, 90, hello, reflect]
*/
  •  運行配置文件中指定類的指定方法

/*
    練習2:通過配置文件運行類中的方法
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
/*        Teacher tea = new Teacher();
        tea.teach();

        Student stu = new Student();
        //private void study
        */
        /*
            class.txt
            className=xxx
            methodName=xxx
         */
        //加載數據
        FileReader fr = new FileReader("E:\\work_space\\java_work\\java_test\\src\\com\\Test\\conf.txt");
        Properties prop = new Properties();
        prop.load(fr);
        System.out.println(prop);

        //通過反射來調用方法
        Class obClass = Class.forName(prop.getProperty("className"));
        Constructor constructor = obClass.getConstructor();
        Object o = constructor.newInstance();

        Method method = obClass.getDeclaredMethod(prop.getProperty("methodName"));
        method.setAccessible(true);
        method.invoke(o);

        //通過反射來調用方法
        Class obClass2 = Class.forName(prop.getProperty("className2"));
        Constructor constructor2 = obClass2.getConstructor();
        Object o2 = constructor2.newInstance();

        Method method2 = obClass2.getDeclaredMethod(prop.getProperty("methodName2"));
        method2.setAccessible(true);
        method2.invoke(o2);
    }
}

/*
{methodName=teach, methodName2=study, className=com.Test.Teacher, className2=com.Test.Student}
老師教學!
學生學習!
*/
  • 模塊化

模塊化概述【理解】                                                                               

Java語言隨着這些年的發展已經成爲了一門影響深遠的編程語言,無數平臺,系統都採用Java語言編寫。但是,伴隨着發展,Java也越來越龐大,逐漸發展成爲一門臃腫的語言。而且,無論是運行一個大型的軟件系統,還是運行一個小的程序,即使程序只需要使用Java的部分核心功能, JVM也要加載整個JRE環境。 爲了給Java“瘦身,讓Java實現輕量化,Java 9正式的推出了模塊化系統。Java被拆分爲N多個模塊,並允許Java程序可以根據需要選擇加載程序必須的Java模塊,這樣就可以讓Java以輕量化的方式來運行

其實,Java 7的時候已經提出了模塊化的概念,但由於其過於複雜,Java 7Java 8都一直未能真正推出,直到Java 9才真正成熟起來。對於Java語言來說,模塊化系統是一次真正的自我革新,這種革新使得古老而龐大Java語言重新煥發年輕的活力

 

package com.toroidal01;

public class Studnet {
    public void study(){
        System.out.println("學生學習!");
    }
}


module myOne {
    exports com.toroidal01;
}

module myTow {
    requires myOne;
}


package com.toroidal;

import com.toroidal01.Studnet;

public class Test {
    public static void main(String[] args) {
        Studnet stu = new Studnet();
        stu.study();
    }
}
  • 模塊服務的基本使用

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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