java 有哪些反射机制_Java 的反射机制你了解多少?
不知道多少次聽說過了Java反射機制的使用,比如:Spring 框架如何實例化IoC容器中的Bean,編碼過程中如何動態(tài)的清理對象中的字段信息等等。工作中只是聽說、看同事們編碼實踐,但是自己卻只是概念上的認識,淺顯粗略,今天就補一下反射的知識點,自己欠下的債,遲早是要還的。
一. 什么是反射?
在運行狀態(tài)中,對于任意一個類,都能夠獲取到這個類的所有屬性和方法,對于任意一個對象,都能夠調用它的任意一個方法和屬性(包括私有的方法和屬性),這種動態(tài)獲取的信息以及動態(tài)調用對象方法的功能就稱為java語言的反射機制。通俗點講,通過反射,該類對我們來說是完全透明的,想要獲取任何東西都可以。
想要使用反射機制,就必須要先獲取到該類的字節(jié)碼文件對象(.class),通過字節(jié)碼文件對象,就能夠通過該類中的方法獲取到我們想要的所有信息(方法,屬性,類名,父類名,實現的所有接口等等),每一個類對應著一個字節(jié)碼文件也就對應著一個Class類型的對象,也就是字節(jié)碼文件對象。
獲取類的字節(jié)碼文件對象有三種方式:
Class clazz1 = Class.forName("全限定類名"); // 通過Class類中的靜態(tài)方法forName,直接獲取到一個類的字節(jié)碼文件對象,此時該類還是源文件階段,并沒有變?yōu)樽止?jié)碼文件。
Class clazz2 = User.class; // 當類被加載成.class文件時,此時Person類變成了.class,在獲取該字節(jié)碼文件對象,也就是獲取自己, 該類處于字節(jié)碼階段。
User user = new User();
Class clazz3 = p.getClass(); // 通過類的實例獲取該類的字節(jié)碼文件對象,該類處于創(chuàng)建對象階段
有了字節(jié)碼文件對象才能獲得類中所有的信息,我們在使用反射獲取信息時,也要考慮使用上面哪種方式獲取字節(jié)碼對象合理,視不同情況而定。下面介紹Class類的功能。
二. 反射機制能夠動態(tài)獲取類的哪些信息?
2.1 通過字節(jié)碼對象創(chuàng)建實例對象
// 通過字節(jié)碼對象創(chuàng)建實例對象
Class> userClz1 = Class.forName("com.base.reflect.entity.User");
User user1 = (User) userClz1.newInstance();
log.info("userClz1 instance = {}", user1);
Class> userClz2 = User.class;
User user2 = (User) userClz1.newInstance();
log.info("userClz1 instance = {}", user2);
2.2 獲取指定構造器方法,constructor 有參無參創(chuàng)建實例
// 獲取指定構造器,有參無參構造實例對象
Class> userClz3 = Class.forName("com.base.reflect.entity.User");
Constructor> constructor1 = userClz3.getConstructor();
User user3 = (User) constructor1.newInstance();
log.info("constructor1 user3 = {}", user3);
Constructor> constructor2 = userClz3.getConstructor(String.class, String.class, String.class, Date.class, String.class, Date.class);
User user4 = (User) constructor2.newInstance("admin", "123456", "admin", new Date(), "admin", new Date());
log.info("constructor user4 = {}", constructor2);
總結上面創(chuàng)建實例對象:
a)Class類的 newInstance() 方法是使用該類無參的構造函數創(chuàng)建對象;
b)可以調用Class類的?getConstructor(Class>... parameterTypes) 方法獲取一個指定參數的構造函數,然后再調用Constructor類的newInstance(value1, value2 ...)方法創(chuàng)建對象;
獲取類中全部構造方法:
// 獲取當前類中 public 類型的構造函數
Constructor>[] constructors = userClz3.getConstructors();
// 獲取當前類中 public protected default private 類型的構造函數
Constructor>[] declaredConstructors = userClz3.getDeclaredConstructors();
2.3 獲取指定的方法,動態(tài)調用方法
// 動態(tài)獲取類中的方法
User user5 = new User("lisi", "123456", "lisi", new Date(), "lisi", new Date());
log.info("user5 = {}", user5);
// 獲取User類中的 setParams 方法,并指定方法中的參數類型
Method method = user5.getClass().getMethod("setParams", String.class, String.class);
// 執(zhí)行方法,傳遞參數【指明運行哪個對象中的哪個方法】
method.invoke(user5,"hello", "123123");
log.info("user5 = {}", user5);
輸出結果:
user5 = User(username=lisi, password=123456, createBy=lisi, createTime=Thu Oct 22 17:21:52 CST 2020, updateBy=lisi, updateTime=Thu Oct 22 17:21:52 CST 2020)
user5 = User(username=hello, password=123123, createBy=lisi, createTime=Thu Oct 22 17:21:52 CST 2020, updateBy=lisi, updateTime=Thu Oct 22 17:21:52 CST 2020)
總結上面動態(tài)調用類中的方法:
Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...) 方法可以獲取類中的指定方法,如果為私有方法,則需要打開一個私有方法權限。
setAccessible(true);用 invoke(Object, Object...) 可以調用該方法;
獲取類中全部方法:
// 獲取當前類中 public 類型的方法
Method[] methods = User.class.getMethods();
// 獲取當前類中 public protected default private 類型的方法
Method[] declaredMethods = User.class.getDeclaredMethods();
2.4 獲取指定的字段,動態(tài)設置對象中字段的值
// 動態(tài)獲取對象中的 Field
User user6 = new User("zhangsan", "123456", "zhangsan", new Date(), "zhangsan", new Date());
log.info("user6 = {}", user1);
clearFields(user6, "createBy", "createTime", "updateBy", "updateTime");
log.info("user6 = {}", user6);
// 清理對象中的字段信息
private static void clearFields(User user1, String... params) throws IllegalAccessException, NoSuchFieldException {
for (String param : params) {
Field field = user1.getClass().getDeclaredField(param);
field.setAccessible(true);
Object obj = field.get(user1);
log.info("obj = {}", obj);
field.set(user1, null);
}
}
輸出結果:
user6 = User(username=zhangsan, password=123456, createBy=zhangsan, createTime=Thu Oct 22 17:33:18 CST 2020, updateBy=zhangsan, updateTime=Thu Oct 22 17:33:18 CST 2020)
obj = zhangsan
obj = Thu Oct 22 17:33:18 CST 2020
obj = zhangsan
user6 = User(username=zhangsan, password=123456, createBy=null, createTime=null, updateBy=null, updateTime=null)
獲取類中全部字段信息:
// 獲取當前類中 public 類型的字段
Field[] fields = User.class.getFields();
// 獲取當前類中 public protected default private 類型的字段
Field[] fields = User.class.getDeclaredFields();
使用場景:在使用 MyBatis 攔截器?Interceptor 對應用添加、更新對象時,需要重新設置 createBy createTime updateBy updateTime 字段信息,動態(tài)的清理一些字段信息,然后重新設置。
總結
以上是生活随笔為你收集整理的java 有哪些反射机制_Java 的反射机制你了解多少?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java spring工作原理_Spri
- 下一篇: java常见_Java 常用类