Java反射機(jī)制的簡(jiǎn)單講解
🌱1. 什么是反射機(jī)制?
首先大家應(yīng)該先了解兩個(gè)概念,編譯期和運(yùn)行期,編譯期就是編譯器幫你把源代碼翻譯成機(jī)器能識(shí)別的代碼,比如編譯器把java代碼編譯成jvm識(shí)別的字節(jié)碼文件,而運(yùn)行期指的是將可執(zhí)行文件交給操作系統(tǒng)去執(zhí)行,JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱(chēng)為java語(yǔ)言的反射機(jī)制
簡(jiǎn)單說(shuō),反射機(jī)制值得是程序在運(yùn)行時(shí)能夠獲取自身的信息。在java中,只要給定類(lèi)的名字,那么就可以通過(guò)反射機(jī)制來(lái)獲得類(lèi)的所有信息。
🌱2. java反射機(jī)制提供了什么功能?
- 在運(yùn)行時(shí)能夠判斷任意一個(gè)對(duì)象所屬的類(lèi)
- 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類(lèi)的對(duì)象
- 在運(yùn)行時(shí)判斷任意一個(gè)類(lèi)所具有的成員變量和方法
- 在運(yùn)行時(shí)調(diào)用任一對(duì)象的方法
- 在運(yùn)行時(shí)創(chuàng)建新類(lèi)對(duì)象
🌱3.new和反射創(chuàng)建有什么區(qū)別呢?
new: 靜態(tài)編譯,在編譯期就將模塊編譯進(jìn)來(lái),執(zhí)行該字節(jié)碼文件,所有的模塊都被加載;
反射:動(dòng)態(tài)編譯,編譯期沒(méi)有加載,等到模塊被調(diào)用時(shí)才加載;
注:spring的ioc就用到反射機(jī)制,newInstance創(chuàng)建。更加的通用,并且降低耦合,避免了硬編碼,只需提供一個(gè)字符串就可以動(dòng)態(tài)的創(chuàng)建。
String className = readfromXMlConfig;//從xml 配置文件中獲得字符串 Class c = Class.forName(className); factory = (AInterface)c.newInstance();
舉例:
有自行車(chē)🚲,小轎車(chē)🚗,
靜態(tài):上班將自行車(chē)放車(chē)?yán)锶ド习?,一定得帶著,一個(gè)不能落下,
動(dòng)態(tài):將自行車(chē)放家里,交通堵塞騎自行車(chē)去,車(chē)放家里。
🌱4. 如何通過(guò)反射調(diào)用私有對(duì)象?
Field[] declaredFields = clazz.getDeclaredFields(); for (Field f : declaredFields) { System.out.println("屬性的名稱(chēng):" + f.getName()); System.out.println("屬性的類(lèi)型:" + f.getType().getName()); // 給屬性賦值 f.setAccessible(true);// 設(shè)置為私有屬性可以訪問(wèn)
🌱5.如何通過(guò)反射調(diào)用方法?
Method m = stuClass.getMethod("show1", String.class); System.out.println(m); //實(shí)例化一個(gè)Student對(duì)象 Object obj = stuClass.getConstructor().newInstance(); m.invoke(obj, "劉德華");
🌱6. class類(lèi)一部分常用方法總結(jié)
- 獲取公共構(gòu)造器 getConstructors()
- 獲取所有構(gòu)造器getDeclaredConstructors
- 獲取包含的方法 getMethod()
- 獲取包含的屬性 getField(String name)
- 獲取內(nèi)部類(lèi) getDeclaredClasses()
- 獲取外部類(lèi)getDeclaringClass()
- 獲取所實(shí)現(xiàn)的接口 getInterfaces()
- 獲取修飾符 getModifiers()
- 獲取所在包 getPackage()
- 獲取類(lèi)名包含包路徑 getName()
java反射的簡(jiǎn)單演示
package com.fjh; 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 Student(String name, int age) { this.name = name; this.age = age; } public Student() { System.out.println("實(shí)例化一個(gè)對(duì)象!"); } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } } package com.fjh; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ReflectTest { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { // 普通方法創(chuàng)建一個(gè)對(duì)象 Student stu = new Student(); // 利用反射機(jī)制創(chuàng)建一個(gè)對(duì)象 Student newInstance = Student.class.newInstance(); // 通過(guò)字節(jié)碼獲取屬性 Class clazz = Student.class; // Field field = clazz.getField("name");//指定返回一個(gè)公有的屬性 Field field = clazz.getDeclaredField("name"); System.out.println("屬性的名稱(chēng):" + field.getName()); System.out.println("屬性的類(lèi)型:" + field.getType().getName()); System.out.println("---------------------"); // 獲取一個(gè)類(lèi)中的所有屬性 Field[] declaredFields = clazz.getDeclaredFields(); for (Field f : declaredFields) { System.out.println("屬性的名稱(chēng):" + f.getName()); System.out.println("屬性的類(lèi)型:" + f.getType().getName()); // 給屬性賦值 f.setAccessible(true);// 設(shè)置為私有屬性可以訪問(wèn) if (int.class == f.getType()) { f.set(newInstance, 50); } else if (String.class == f.getType()) { f.set(newInstance, "蔡徐坤"); } } System.out.println("========通過(guò)直接賦值后的結(jié)果=========="); System.out.println(newInstance); System.out.println("========獲取所有方法=========="); // 獲取所有方法 不包括構(gòu)造方法 Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { String methodName = method.getName();// 參數(shù)名稱(chēng) int parameterCount = method.getParameterCount();// 參數(shù)個(gè)數(shù) System.out.println("方法名字:" + methodName); System.out.println("方法參數(shù)個(gè)數(shù):" + parameterCount); Class<?>[] parameterTypes = method.getParameterTypes(); // 獲取每個(gè)方法的參數(shù)類(lèi)型 for (Class<?> class1 : parameterTypes) { System.out.println("參數(shù)類(lèi)型:" + class1.getName()); } // 獲取方法的返回值 Class<?> returnType = method.getReturnType(); System.out.println("方法的返回值為:" + returnType.getName()); System.out.println("-------------------"); } // 執(zhí)行獲取到的 方法 // 如果方法參數(shù)有多個(gè),則需要用字節(jié)碼數(shù)組來(lái)代替 // Method declaredMethod = clazz.getDeclaredMethod("setName", new // Class[]{String.class,int.class}); // 執(zhí)行方法同樣使用數(shù)組 // declaredMethod.invoke(newInstance,Object[]{"mayun",20} ); Method declaredMethod = clazz.getDeclaredMethod("setName", String.class);// 返回當(dāng)前Class對(duì)象表示的類(lèi)或接口的指定已說(shuō)明的一個(gè)方法對(duì)象。 declaredMethod.invoke(newInstance, "馬云"); System.out.println("==========設(shè)值注入========="); System.out.println(newInstance); // 構(gòu)造函數(shù) Constructor constructor = clazz.getConstructor(new Class[] { String.class, int.class }); // 如何執(zhí)行構(gòu)造函數(shù) Object obj = constructor.newInstance(new Object[] { "周杰倫", 46 }); System.out.println("==========構(gòu)造注入========="); System.out.println(obj); System.out.println("==========構(gòu)造方法========="); //獲取所有的構(gòu)造函數(shù) Constructor[] constructors = clazz.getConstructors(); for (Constructor c : constructors) { if(c.getParameterCount() != 0){ Class[] parameterTypes = c.getParameterTypes(); for (Class class1 : parameterTypes) { System.out.println("參數(shù)類(lèi)型:"+class1.getTypeName()); } System.out.println("-------------------"); }else{ System.out.println("無(wú)參構(gòu)造"); System.out.println("-------------------"); } } } }
🌱7. 結(jié)果
到此這篇關(guān)于Java反射機(jī)制的簡(jiǎn)單講解的文章就介紹到這了,更多相關(guān)Java反射機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于java流實(shí)現(xiàn)壓縮圖片過(guò)程解析
這篇文章主要介紹了基于java流實(shí)現(xiàn)壓縮圖片過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Java中的三種校驗(yàn)注解的使用(@Valid,@Validated和@PathVariable)
本文主要介紹了Java中的三種校驗(yàn)注解的使用(@Valid,@Validated和@PathVariable),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04java實(shí)現(xiàn)簡(jiǎn)單的小超市程序
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的小超市程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02hibernate一對(duì)多關(guān)聯(lián)映射學(xué)習(xí)小結(jié)
這篇文章主要介紹了hibernate一對(duì)多關(guān)聯(lián)映射學(xué)習(xí)小結(jié),需要的朋友可以參考下2017-09-09Spring Boot使用RestTemplate消費(fèi)REST服務(wù)的幾個(gè)問(wèn)題記錄
這篇文章主要介紹了Spring Boot使用RestTemplate消費(fèi)REST服務(wù)的幾個(gè)問(wèn)題記錄,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06Java中l(wèi)ist集合為空或?yàn)閚ull的區(qū)別說(shuō)明
這篇文章主要介紹了Java中l(wèi)ist集合為空或?yàn)閚ull的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11