Java反射-創(chuàng)新互聯(lián)

快速定位
  • 前言
  • 1. 類加載器?
    • 1.1 類加載器
    • 1.2 類加載的過程
    • 1.3 加載器的分類
    • 1.4 雙親委派模型
    • 1.5 類加載器中兩個(gè)重要的方法:
  • 2. 反射
    • 2.1 反射的概述
    • 2.2 獲取Class對象的三種方式
    • 2.3 獲取Class類對象中的內(nèi)容
    • 2.4 反射獲取構(gòu)造方法
      • 2.4.1 Class類獲取構(gòu)造方法對象的方法
      • 2.4.2 通過Constructor對象中的方法創(chuàng)建對象
      • 2.4.3 小結(jié)
    • 2.5 反射獲取成員變量
      • 2.5.1 Class類獲取成員變量對象的方法
      • 2.5.2 給成員變量賦值
    • 2.6 反射獲取成員方法并使用
      • 2.6.1 Class類獲取成員方法對象的方法
  • 3. 總結(jié)

成都創(chuàng)新互聯(lián)公司主營合江網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都App制作,合江h(huán)5小程序設(shè)計(jì)搭建,合江網(wǎng)站營銷推廣歡迎合江等地區(qū)企業(yè)咨詢
前言

Java的反射(reflection)機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個(gè)類的對象,可以了解任意一個(gè)對象所屬的類,可以了解任意一個(gè)類的成員變量和方法,可以調(diào)用任意一個(gè)對象的屬性和方法。這種動態(tài)獲取程序信息以及動態(tài)調(diào)用對象的功能稱為Java語言的反射機(jī)制。反射被視為動態(tài)語言的關(guān)鍵。


1. 類加載器? 1.1 類加載器

了解Java反射機(jī)制前先了解一下類加載器相關(guān)的知識。java文件 經(jīng)過編譯 ->Class文件(字節(jié)碼文件) 最后虛擬機(jī)執(zhí)行的就是字節(jié)碼文件, 但是字節(jié)碼文件又不會自己跑到虛擬機(jī)當(dāng)中, 這時(shí)候就得需要一個(gè)”人“,把字節(jié)碼文件放到虛擬機(jī)當(dāng)中,而這個(gè)人就是 類加載器。
在這里插入圖片描述

1.2 類加載的過程

類加載時(shí)機(jī)(何時(shí)加載字節(jié)碼文件):

  • 創(chuàng)建類的實(shí)例(對象)
  • 調(diào)用類的類方法(靜態(tài)方法)
  • 訪問類或者接口的類變量(靜態(tài)變量),或者為該類賦值
  • 使用反射方式來強(qiáng)制的創(chuàng)建某個(gè)類或接口對應(yīng)的java.lang.Class對象
  • 初始化某一個(gè)類的子類(當(dāng)你需要創(chuàng)建一個(gè)類的對象,那么也- - 要把這個(gè)類的父類 的字節(jié)碼文件也加載到內(nèi)存當(dāng)中。
  • 直接使用java.exe命令來運(yùn)行某個(gè)主類
    這么多情況,心好累,記不住?。?br />在這里插入圖片描述

總結(jié):用到就加載,不用不加載

類加載過程

  1. 加載
  • 通過一個(gè)類的全限定名(包名+類名)來獲取定義此類的二進(jìn)制字節(jié)流 —》 通過包名+類名,獲取這個(gè)類,準(zhǔn)備用流進(jìn)行傳輸
  • 將這個(gè)字節(jié)流所代表的的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為運(yùn)行時(shí)的存儲結(jié)構(gòu) —》 把這個(gè)類加載到內(nèi)存當(dāng)中
  • 在內(nèi)存中會生成一個(gè)代表這個(gè)類的java.lang.Class對象,任何類被使用時(shí),系統(tǒng)都會為之建立一個(gè)java.lang.Class對象 —》加載完畢創(chuàng)建一個(gè)Class對象
    在這里插入圖片描述
    在這里插入圖片描述
  1. 鏈接
  • 驗(yàn)證
    在這里插入圖片描述

  • 準(zhǔn)備
    在這里插入圖片描述

  • 解析
    在這里插入圖片描述
    解析過程拆解:
    name的類型是引用類型(String),String是其他的類的名字,最初加載String類的時(shí)候不知道String類在哪里,這時(shí)的String使用符號(ex:&&&)替代。在解析的過程中,就會找實(shí)際的String類在哪里,并把臨時(shí)的符號變成實(shí)際的String引用
    在這里插入圖片描述

  1. 初始化
    在這里插入圖片描述
1.3 加載器的分類
  • 分類
    啟動類加載器(Bootstrap ClassLoader):虛擬機(jī)內(nèi)置的類加載器
    平臺類加載器(Platform Classloader):負(fù)責(zé)加載JDK中一些特殊的模塊
    系統(tǒng)類加載器(System Classloader):負(fù)責(zé)加載用戶類路徑上所指定的類庫
  • 類加載器的繼承關(guān)系
    System的父加載器為Platform
    Platform的父加載器為Bootstrap
  • 代碼演示
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 獲取系統(tǒng)類加載器的父類加載器,平臺類加載器
ClassLoader clasLoader1 = systemClassLoader.getParent();
//獲取平臺類加載器的父類加載器, 啟動類加載器
ClassLoader classLoader2 = clasLoader1.getParent();
System.out.println("系統(tǒng)類加載器" + systemClassLoader);
System.out.println("平臺類加載器" + clasLoader1);
System.out.println("啟動類加載器" + classLoader2);
1.4 雙親委派模型
  • 介紹
    如果一個(gè)類加載器收到了類加載請求,它并不會自己先去加載,而是把這個(gè)請求委托給父類的加載器去執(zhí)行,如果父類加載器還存在其父類加載器,則進(jìn)一步向上委托,依次遞歸,請求最終將到達(dá)頂層的啟動類加載器,如果父類加載器可以完成類加載任務(wù),就成功返回,倘若父類加載器無法完成此加載任務(wù),子加載器才會嘗試自己去加載,這就是雙親委派模式
    邏輯上的繼承(不是extend)。
    在這里插入圖片描述
1.5 類加載器中兩個(gè)重要的方法:
  • 方法介紹
方法名說明
public static ClassLoader getSystemClassLoader()獲取系統(tǒng)類加載器
public InputStream getResourceAsStream(String name)加載某一個(gè)資源文件
  • 代碼演示
//獲得系統(tǒng)類加載器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 利用類加載器去加載一個(gè)指定的文件
// 參數(shù):文件的路徑
// 返回值:字節(jié)流
// 這里直接填寫prop.properties,相對的在src下邊
InputStream resourceAsStream = systemClassLoader.getResourceAsStream("prop.properties");
Properties properties = new Properties();
    properties.load(resourceAsStream);
    System.out.println(properties);
    resourceAsStream.close();
2. 反射 2.1 反射的概述

Java反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類所有的屬性與方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意屬性和方法(利用反射調(diào)用它類中的屬性和方法時(shí),無視修飾符)。
這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為Java語言的反射機(jī)制(先獲取配置文件中的信息,動態(tài)獲取信息并創(chuàng)建對象和調(diào)用方法)

2.2 獲取Class對象的三種方式
  • 思考
    如何使用反射去調(diào)用一個(gè)類中的方法
    利用class對象來創(chuàng)建
    反射方式:創(chuàng)建對象
    反射方式:調(diào)用方法
  • 三種方式分類
    類名.class屬性
    對象名.getClass()方法
    Class.forName(全類名)方法
    在這里插入圖片描述
  • 代碼演示
    student類
public class Student {private String name;
private int age;
public Student() {}

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

public String getName() {return name;
}

public void setName(String name) {this.name = name;
}

public int getAge() {return age;
}

public void setAge(int age) {this.age = age;
}

public void study(){System.out.println("學(xué)生在學(xué)習(xí)");
}

@Override
public String toString() {return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
}
}
  • main方法
Classclazz = Class.forName("全類名");
Classclazz2 = Student.class;
Student s = new Student();
//每一個(gè)對象都對應(yīng)著一個(gè)字節(jié)碼文件,所以getClass方法是定義在Object中的
Class clazz3 = s.getClass();
System.out.println(clazz == clazz2);//true
System.out.println(clazz3 == clazz2);//true
2.3 獲取Class類對象中的內(nèi)容

Java當(dāng)中什么都可以看成一個(gè)對象,只要是對象,就可以用類去描述。從class類中獲取的成員變量就可以把它認(rèn)為是成員變量對象(Field),以此類推…

如何學(xué)習(xí)?
大概步驟(以獲取構(gòu)造方法為例)
-獲取class對象
-獲得Constructor對象
-創(chuàng)建對象
明白幾個(gè)問題
-獲取對象不就是為了創(chuàng)建對象么?
-獲取屬性不就是為了給他賦值和取值么?
-獲取方法不就是為了調(diào)用么?
學(xué)習(xí)
-把整個(gè)流程以及為什么用反射了解清楚,方法忘了就去api手冊查,重復(fù)多了自然也就記住了
總結(jié)
-先獲取整體(Class對象),在獲取部分(成員屬性,構(gòu)造方法,成員男方法),然后操作部分

如圖所示:Class對象加載到內(nèi)存當(dāng)中,我們可以去獲取想要的信息
在這里插入圖片描述

2.4 反射獲取構(gòu)造方法 2.4.1 Class類獲取構(gòu)造方法對象的方法
方法名說明
Constructor[] getConstructors()返回所有公共構(gòu)造方法對象的數(shù)組
Constructor[] getDeclaredConstructors()返回所有構(gòu)造方法對象的數(shù)組
Constructor getConstructor(Class… parameterTypes)返回單個(gè)公共構(gòu)造方法對象
Constructor getDeclaredConstructor(Class… parameterTypes)返回單個(gè)構(gòu)造方法對象
  • 代碼演示
    Student.java
public class Student {private String name;
    private int age;
    public String getName() {return name;
    }
    public void setName(String name) {this.name = name;
    }
    public int getAge() {return age;
    }
    public void setAge(int age) {this.age = age;
    }
    public void study() {System.out.println("我的名字是:" + name);
        System.out.println("學(xué)生在打籃球");
    }
    private Student(String name) {System.out.println("name的值為:" + name + "age的值為:" + age);
        System.out.println("private ... student ... 有參構(gòu)造方法");
    }
    public Student() {System.out.println("public ... student ... 無參構(gòu)造方法");
    }
    public Student(String name, int age) {System.out.println("name的值為:" + name + "age的值為:" + age);
        System.out.println("public ... student ... 有參構(gòu)造方法");
    }
    @Override
    public String toString() {return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

main

private static void method4() throws ClassNotFoundException, NoSuchMethodException {Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
    Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
    System.out.println(declaredConstructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
    //小括號中一定要和構(gòu)造方法的形參保持一致
    Constructorconstructor = clazz.getConstructor();
    System.out.println(constructor);
    Constructorconstructor2 = clazz.getConstructor(String.class, int.class);
    System.out.println(constructor2);
    //會報(bào)錯,沒有形參為int的構(gòu)造方法
    Constructorconstructor3 = clazz.getConstructor(int.class);
    System.out.println(constructor3);
}
private static void method2() throws ClassNotFoundException {Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
    Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
    for (ConstructordeclaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);
    }
}
private static void method1() throws ClassNotFoundException {Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
    Constructor[] constructors = clazz.getConstructors();
    for (Constructorconstructor : constructors) {System.out.println(constructor);
    }
}
2.4.2 通過Constructor對象中的方法創(chuàng)建對象
  • 方法介紹
方法名說明
T newInstance(Object…initargs)根據(jù)指定的構(gòu)造方法創(chuàng)建對象
setAccessible(boolean flag)設(shè)置為true,表示取消訪問檢查
  • 代碼演示
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//        method1();
//        method2();
//        method3();
        //獲取一個(gè)私有的構(gòu)造方法,并創(chuàng)建對象
        //1.獲取class對象
        Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
        //2.獲取一個(gè)私有化的構(gòu)造方法
        Constructor constructor = clazz.getDeclaredConstructor(String.class);
        //被private修飾的成員,不能直接使用
        //如果使用反射前行獲取并使用,需要臨時(shí)取消訪問檢查
        constructor.setAccessible(true);
        //3.直接創(chuàng)建對象
        Student student = (Student) constructor.newInstance("李白");
        System.out.println(student);
    }
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException { //簡寫格式
     Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
     Student student = (Student) clazz.newInstance();//這個(gè)方法過時(shí)了
 }
private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
     Constructorconstructor = clazz.getConstructor();
     Student student = (Student) constructor.newInstance();
     System.out.println(student);
 }
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { // 獲取class對象
     Classclazz = Class.forName("com.gosling.reflect.Entity.Student");
     //獲取構(gòu)造方法對象
     Constructorconstructor = clazz.getConstructor(String.class, int.class);
     //利用newInstance方法,創(chuàng)建Student對象
     Student student = (Student) constructor.newInstance("李白", 61);
     System.out.println(student);
 }
2.4.3 小結(jié)
  • 獲取class對象
    三種方式: Class.forName(“全類名”), 類名.class, 對象名.getClass()
  • 獲取里面的構(gòu)造方法對象
    getConstructor (Class... parameterTypes)getDeclaredConstructor (Class… parameterTypes)
  • 如果是public的,直接創(chuàng)建對象
    newInstance(Object… initargs)
  • 如果是非public的,需要臨時(shí)取消檢查,然后再創(chuàng)建對象
    setAccessible(boolean) 暴力反射
2.5 反射獲取成員變量 2.5.1 Class類獲取成員變量對象的方法
  • 方法介紹
方法名說明
Field[] getFields()返回所有公共(public)成員變量對象的數(shù)組
Field[] getDeclaredFields()返回所有成員變量對象的數(shù)組
Field getField(String name)返回單個(gè)公共成員變量對象
Field getDeclaredField(String name)返回單個(gè)成員變量對象
  • 代碼演示
private static void method4() throws ClassNotFoundException, NoSuchFieldException {//1.獲取class對象
    Classclazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取name這個(gè)成員變量
    Field field = clazz.getDeclaredField("money");
    //3.打印
    System.out.println(field);
}

private static void method3() throws ClassNotFoundException, NoSuchFieldException {//想要獲取的成員變量必須是真是存在的,且是public的
    //1.獲取class對象
    Classclazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取name這個(gè)成員變量
    Field field = clazz.getField("money");
    //3.打印
    System.out.println(field);
}

private static void method2() throws ClassNotFoundException {//1.獲取class對象
    Classclazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取Field對象
    Field[] fields = clazz.getDeclaredFields();
    //3.遍歷
    for (Field field : fields) {System.out.println(field);
    }
}

private static void method1() throws ClassNotFoundException {//1.獲取class對象
    Classclazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取Field對象
    Field[] fields = clazz.getFields();
    //3.遍歷
    for (Field field : fields) {System.out.println(field);
    }
}
2.5.2 給成員變量賦值
  • 方法介紹
方法名說明
void set(Object obj, Object value)賦值
Object get(Object obj)獲取值
  • 代碼演示
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {//        method1();
        //1.獲取class對象
        Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
        //2.獲取成員變量的Field對象
        Field field = clazz.getDeclaredField("money");
        //3.取消訪問檢查
        field.setAccessible(true);
        //4.調(diào)用get方法來取值
        //4.1創(chuàng)建一個(gè)對象
        Person person = (Person) clazz.newInstance();
        //4.2獲取指定對象的money的值
        Object o = field.get(person);
        //5.打印
        System.out.println(o);

    }
    private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {//1.獲取class對象
        Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
        // 2.獲取name這個(gè)Field對象
        Field field = clazz.getField("name");
        //3.利用set方法進(jìn)行賦值
        //3.1先創(chuàng)建一個(gè)Student對象
        Person person = (Person) clazz.newInstance();
        //3.2有了對象才可以給指定對象賦值
        field.set(person,"李白");
        System.out.println(person);
    }
2.6 反射獲取成員方法并使用 2.6.1 Class類獲取成員方法對象的方法
  • 方法分類
方法名
Method[] getMethods()返回所有公共成員方法對象的數(shù)組,包括繼承的
Method[] getDeclaredMethods()返回所有成員方法對象的數(shù)組,不包括繼承的
Method getMethod(String name, Class… parameterTypes)返回單個(gè)公共成員方法對象
Method getDeclaredMethod(String name, Class… parameterTypes)返回單個(gè)成員方法對象
  • 代碼演示
private static void method5() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
    Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取私有的方法
    Method look = clazz.getDeclaredMethod("look");
    System.out.println(look);
}

private static void method4() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
    Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取有形參的方法
    Method method1 = clazz.getMethod("method2", String.class);
    System.out.println(method1);
}

private static void method3() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
    Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取無參數(shù)的方法
    Method method1 = clazz.getMethod("method1");
    System.out.println(method1);
}


private static void method2() throws ClassNotFoundException {//1.獲取class對象
    Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取成員方法對象
    Method[] methods = clazz.getDeclaredMethods();// 返回所有成員方法的數(shù)組,不包含繼承的
    for (Method method : methods) {System.out.println(method);
    }
}

private static void method1() throws ClassNotFoundException {//1.獲取class對象
    Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
    //2.獲取成員方法對象
    Method[] methods = clazz.getMethods();// 繼承父類的方法也在里邊
    for (Method method : methods) {System.out.println(method);
    }
}

3. 總結(jié)

以上就是今天要講的內(nèi)容,本文僅僅簡單介紹了Java的反射機(jī)制,因?yàn)橛嘘P(guān)反射的方法眾多,本文只介紹了較為常用的一些去供大家學(xué)習(xí)和了解!
本文中的案例大家不要光看哦,試著放到程序中運(yùn)行一下,對加深理解有很大的幫助的!

最后,創(chuàng)作不易,如果本文對您有一點(diǎn)幫助的話,就點(diǎn)贊、收藏、關(guān)注支持鼓勵一下吧,您的支持是我創(chuàng)作的動力!

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

本文題目:Java反射-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://muchs.cn/article42/phchc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、外貿(mào)網(wǎng)站建設(shè)網(wǎng)站改版、動態(tài)網(wǎng)站、網(wǎng)站排名標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名