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());
// 獲取屬性類型的簡要名稱
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方式反射的對象,會(huì)進(jìn)行初始化(會(huì)執(zhí)行靜態(tài)代碼),而通過getClassLoader方式反射的對象,是不會(huì)進(jìn)行初始化的。
2.2 修飾符的打印
如果想打印方法、屬性的修飾符,我們應(yīng)該通過Modifier類去拿到。請看這一行代碼:
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類型)來做對應(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.測試1:getDeclaredFields打印成員變量:

4.測試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è)類型的全名稱,那么對應(yīng)的getSimpleName就顧名思義,返回的是類型名稱。
對于其他的相關(guān)屬性和API,代碼的注釋都寫的比較詳細(xì)了,就不展開介紹了。
到此這篇關(guān)于Java通過反射來打印類的方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java反射打印類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用泛型Class實(shí)現(xiàn)消除模板代碼
Class作為實(shí)現(xiàn)反射功能的類,在開發(fā)中經(jīng)常會(huì)用到,然而,當(dāng)Class遇上泛型后,事情就變得不是那么簡單了,所以本文就來講講Java如何使用泛型Class實(shí)現(xiàn)消除模板代碼,需要的可以參考一下2023-06-06
關(guān)于Spring的AnnotationAwareAspectJAutoProxyCreator類解析
這篇文章主要介紹了關(guān)于Spring的AnnotationAwareAspectJAutoProxyCreator類解析,Spring是一個(gè)開源免費(fèi)的框架 , 容器,是一個(gè)輕量級的框架 ,需要的朋友可以參考下2023-05-05
Mybatis?Interceptor線程安全引發(fā)的bug問題
這篇文章主要介紹了Mybatis?Interceptor線程安全引發(fā)的bug問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
JavaMail實(shí)現(xiàn)郵件發(fā)送的方法
這篇文章主要介紹了JavaMail實(shí)現(xiàn)郵件發(fā)送的方法,實(shí)例分析了java實(shí)現(xiàn)郵件發(fā)送的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
java實(shí)現(xiàn)電腦定時(shí)關(guān)機(jī)的方法
這篇文章主要介紹了java實(shí)現(xiàn)電腦定時(shí)關(guān)機(jī)的方法,首先通過java注冊windows服務(wù)程序,再以一個(gè)簡單的java程序?qū)崿F(xiàn)定時(shí)關(guān)機(jī)的功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-11-11
java?環(huán)境配置(2023年詳細(xì)教程)
這篇文章首先為了完善我的知識(shí)體系,今后一些軟件的安裝教程也可能會(huì)用到想寫一個(gè)更加詳細(xì)的,因?yàn)檫@并不僅僅是寫給?IT?行業(yè)的,其它行業(yè)可能也需要配置java環(huán)境2023-06-06
Java中的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

