Java通過反射來打印類的方法實(shí)現(xiàn)
工作了有一段時(shí)間了,我覺得是時(shí)候去復(fù)習(xí)下Java的一些基礎(chǔ)知識(shí),因此寫下了這篇文章。平常開發(fā)過程中,前端寫的比較多,后端也不能忘!
一. 案例出發(fā)
先準(zhǔn)備一個(gè)模板類:
public class User { public int id; private String name; public User(String name, int id) { this.id = id; this.name = name; } private User(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
開始反射
import java.lang.reflect.*; public class Test { public static final String LINE = "\n"; public static final String SPACE = " "; public static void main(String[] args) throws Exception { Class<?> c = Class.forName("com.User"); // Class<?> c = Test.class.getClassLoader().loadClass("com.User"); StringBuilder sb = new StringBuilder(); // 打印包,類名 String packageName = c.getPackage().getName(); sb.append("package " + packageName + ";" + LINE); sb.append(LINE); sb.append("public class " + c.getSimpleName() + "{" + LINE); // 打印成員變量 Field[] declaredFields = c.getDeclaredFields(); for (Field field : declaredFields) { // Field.getModifiers()返回一個(gè)int類型的數(shù)值,用于標(biāo)識(shí)public、static等標(biāo)識(shí)符 String fieldModifier = Modifier.toString(field.getModifiers()); // 獲取屬性類型的簡(jiǎn)要名稱 String typeName = field.getType().getSimpleName(); // 屬性的名稱 String fieldName = field.getName(); sb.append(SPACE + fieldModifier + " " + typeName + " " + fieldName + ";" + LINE); } sb.append(LINE); // 打印構(gòu)造 Constructor<?>[] declaredConstructors = c.getDeclaredConstructors(); for (Constructor<?> constructor : declaredConstructors) { // 構(gòu)造函數(shù)的標(biāo)識(shí)符 String constructorModifier = Modifier.toString(constructor.getModifiers()); sb.append(SPACE + constructorModifier + " " + c.getSimpleName() + " " + "("); // 打印構(gòu)造函數(shù)的參數(shù) printParam(sb, constructor.getParameterTypes()); } // 打印方法 Method[] methods = c.getDeclaredMethods(); for (Method method : methods) { // 方法的標(biāo)識(shí)符 String methodModifier = Modifier.toString(method.getModifiers()); // 方法返回類型 String returnTypeName = method.getReturnType().getSimpleName(); // 方法名稱 String methodName = method.getName(); sb.append(SPACE + methodModifier + " " + returnTypeName + " " + methodName + "("); printParam(sb, method.getParameterTypes()); } sb.append("}"); System.out.println(sb.toString()); } private static void printParam(StringBuilder sb, Class<?>[] parameterTypes2) { Class<?>[] parameterTypes = parameterTypes2; for (int i = 0; i < parameterTypes.length; i++) { // 參數(shù)的類型 String simpleName = parameterTypes[i].getSimpleName(); if (i == 0) { sb.append(simpleName + " args"); } else { sb.append(", " + simpleName + " args"); } } sb.append(") {" + LINE); sb.append(SPACE + "}" + LINE); sb.append(LINE); } }
最終的結(jié)果如下:
二. 反射方法的分析
2.1 反射的方式
代碼中我們可以發(fā)現(xiàn),這里提供了兩種基本的反射:
Class.forName()
getClassLoader().loadClass()
首先,在模板類中添加靜態(tài)塊代碼:
再來運(yùn)行一下兩種反射方式的代碼:
forName
:
getClassLoader
:
結(jié)論如下:
初始化:通過forName
方式反射的對(duì)象,會(huì)進(jìn)行初始化(會(huì)執(zhí)行靜態(tài)代碼),而通過getClassLoader
方式反射的對(duì)象,是不會(huì)進(jìn)行初始化的。
2.2 修飾符的打印
如果想打印方法、屬性的修飾符,我們應(yīng)該通過Modifier
類去拿到。請(qǐng)看這一行代碼:
String fieldModifier = Modifier.toString(field.getModifiers());
來看下Modifier.toString
的源碼:
public static String toString(int mod) { StringBuilder sb = new StringBuilder(); int len; if ((mod & PUBLIC) != 0) sb.append("public "); if ((mod & PROTECTED) != 0) sb.append("protected "); if ((mod & PRIVATE) != 0) sb.append("private "); /* Canonical order */ if ((mod & ABSTRACT) != 0) sb.append("abstract "); if ((mod & STATIC) != 0) sb.append("static "); if ((mod & FINAL) != 0) sb.append("final "); if ((mod & TRANSIENT) != 0) sb.append("transient "); if ((mod & VOLATILE) != 0) sb.append("volatile "); if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized "); if ((mod & NATIVE) != 0) sb.append("native "); if ((mod & STRICT) != 0) sb.append("strictfp "); if ((mod & INTERFACE) != 0) sb.append("interface "); if ((len = sb.length()) > 0) /* trim trailing space */ return sb.toString().substring(0, len-1); return ""; }
很明顯,其通過語言修飾符的類型(int類型)來做對(duì)應(yīng)的映射并返回。
案例代碼中有三塊地方都支持獲得修飾符類型:
field.getModifiers()
:字段修飾符。constructor.getModifiers()
:構(gòu)造修飾符。method.getModifiers()
:方法的修飾符。
2.3 getDeclaredxxx和getxxx的區(qū)別
以Field為例:
Field[] declaredFields = c.getDeclaredFields(); Field[] fields = c.getFields();
案例如下:
1.新建一個(gè)Parent
類:
public class Parent { public String parentAddress; private Integer Number; }
2.讓User
類繼承Parent
類
3.測(cè)試1:getDeclaredFields
打印成員變量:
4.測(cè)試2:getFields
打印成員變量:
兩者區(qū)別如下:
比較內(nèi)容 | getDeclaredFields | getFields |
---|---|---|
作用的類的范圍 | 僅僅限于當(dāng)前類 | 還可以包括父類 |
作用的修飾符范圍 | 可以獲取public和非public類型 | 只能獲得public類型的相關(guān)值 |
2.4 getSimpleName和getName有什么不同
以這行代碼為例:
String typeName = field.getType().getSimpleName();
若我將getSimpleName
改為getName
,看看輸出結(jié)果會(huì)有什么不同:
可以發(fā)現(xiàn)gatName
輸出的是這個(gè)類型的全名稱,那么對(duì)應(yīng)的getSimpleName
就顧名思義,返回的是類型名稱。
對(duì)于其他的相關(guān)屬性和API,代碼的注釋都寫的比較詳細(xì)了,就不展開介紹了。
到此這篇關(guān)于Java通過反射來打印類的方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java反射打印類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用泛型Class實(shí)現(xiàn)消除模板代碼
Class作為實(shí)現(xiàn)反射功能的類,在開發(fā)中經(jīng)常會(huì)用到,然而,當(dāng)Class遇上泛型后,事情就變得不是那么簡(jiǎn)單了,所以本文就來講講Java如何使用泛型Class實(shí)現(xiàn)消除模板代碼,需要的可以參考一下2023-06-06關(guān)于Spring的AnnotationAwareAspectJAutoProxyCreator類解析
這篇文章主要介紹了關(guān)于Spring的AnnotationAwareAspectJAutoProxyCreator類解析,Spring是一個(gè)開源免費(fèi)的框架 , 容器,是一個(gè)輕量級(jí)的框架 ,需要的朋友可以參考下2023-05-05Mybatis?Interceptor線程安全引發(fā)的bug問題
這篇文章主要介紹了Mybatis?Interceptor線程安全引發(fā)的bug問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02JavaMail實(shí)現(xiàn)郵件發(fā)送的方法
這篇文章主要介紹了JavaMail實(shí)現(xiàn)郵件發(fā)送的方法,實(shí)例分析了java實(shí)現(xiàn)郵件發(fā)送的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04java實(shí)現(xiàn)電腦定時(shí)關(guān)機(jī)的方法
這篇文章主要介紹了java實(shí)現(xiàn)電腦定時(shí)關(guān)機(jī)的方法,首先通過java注冊(cè)windows服務(wù)程序,再以一個(gè)簡(jiǎn)單的java程序?qū)崿F(xiàn)定時(shí)關(guān)機(jī)的功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-11-11java?環(huán)境配置(2023年詳細(xì)教程)
這篇文章首先為了完善我的知識(shí)體系,今后一些軟件的安裝教程也可能會(huì)用到想寫一個(gè)更加詳細(xì)的,因?yàn)檫@并不僅僅是寫給?IT?行業(yè)的,其它行業(yè)可能也需要配置java環(huán)境2023-06-06Java中的HashSet集合存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)詳解
這篇文章主要介紹了Java中的HashSet集合存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)詳解,數(shù)組結(jié)構(gòu)他把元素進(jìn)行分組,相同哈希值的元素是一組,鏈表/紅黑樹結(jié)構(gòu)把相同哈希值的元素鏈接到一起,存儲(chǔ)數(shù)據(jù)到集合中,先計(jì)算元素的哈希值,需要的朋友可以參考下2023-09-09在IntelliJ IDEA中.idea文件是什么可以刪除嗎
相信有很多小伙伴,在用idea寫java代碼的時(shí)候,創(chuàng)建工程總是會(huì)出現(xiàn).idea文件,該文件也從來沒去打開使用過,那么它在我們項(xiàng)目里面,扮演什么角色,到底能不能刪除它呢?這篇文章主要介紹了在IntelliJ IDEA中.idea文件是什么可以刪除嗎,需要的朋友可以參考下2024-01-01