Java框架設(shè)計(jì)靈魂之反射的示例詳解
框架:半成品軟件??梢栽诳蚣艿幕A(chǔ)上進(jìn)行軟件開發(fā),簡化編碼。
反射就是把Java類中的各個成員映射成一個個的Java對象。
即在運(yùn)行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;
對于任意一個對象,都能調(diào)用它的任意一個方法和屬性。
這種動態(tài)獲取信息及動態(tài)調(diào)用對象方法的功能叫Java的反射機(jī)制。
好處:
1. 可以在程序運(yùn)行過程中,操作這些對象。
2. 可以解耦,提高程序的可擴(kuò)展性。
獲取Class對象的方式
1. Class.forName("全類名"):將字節(jié)碼文件加載進(jìn)內(nèi)存,返回Class對象
多用于配置文件,將類名定義在配置文件中。讀取文件,加載類。
2. 類名.class:通過類名的屬性class獲取
多用于參數(shù)的傳遞
3. 對象.getClass():getClass()方法在Object類中定義著。
多用于對象的獲取字節(jié)碼的方式
//1.Class.forName("全類名")
Class cls1 = Class.forName("com.zjq.javabase.base25.domain.Person");
System.out.println(cls1);
//2.類名.class
Class cls2 = Person.class;
System.out.println(cls2);
//3.對象.getClass()
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
結(jié)論:
同一個字節(jié)碼文件(*.class)在一次程序運(yùn)行過程中,只會被加載一次,不論通過哪一種方式獲取的Class對象都是同一個。
Class對象功能
測試的Person類:
package com.zjq.javabase.base25.domain;
/**
* @author zjq
*/
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person() {
}
public Person(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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
public void eat(){
System.out.println("eat...");
}
public void eat(String food){
System.out.println("eat..."+food);
}
}
獲取成員變量們
Field[] getFields() :獲取所有public修飾的成員變量
Field getField(String name) 獲取指定名稱的 public修飾的成員變量
Field[] getDeclaredFields() 獲取所有的成員變量,不考慮權(quán)限修飾符
Field getDeclaredField(String name)
案例:
//0.獲取Person的Class對象
Class personClass = Person.class;
//1.Field[] getFields()獲取所有public修飾的成員變量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------");
//2.Field getField(String name)
Field a = personClass.getField("a");
//獲取成員變量a 的值
Person p = new Person();
Object value = a.get(p);
System.out.println(value);
//設(shè)置a的值
a.set(p,"張三");
System.out.println(p);
System.out.println("===================");
//Field[] getDeclaredFields():獲取所有的成員變量,不考慮修飾符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//Field getDeclaredField(String name)
Field d = personClass.getDeclaredField("d");
//忽略訪問權(quán)限修飾符的安全檢查
d.setAccessible(true);//暴力反射
Object value2 = d.get(p);
System.out.println(value2);
獲取構(gòu)造方法們
Constructor<?>[] getConstructors()
Constructor<T> getConstructor(類<?>... parameterTypes)
Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors()
案例:
//0.獲取Person的Class對象
Class personClass = Person.class;
//Constructor<T> getConstructor(類<?>... parameterTypes)
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println(constructor);
//創(chuàng)建對象
Object person = constructor.newInstance("張三", 23);
System.out.println(person);
System.out.println("----------");
Constructor constructor1 = personClass.getConstructor();
System.out.println(constructor1);
//創(chuàng)建對象
Object person1 = constructor1.newInstance();
System.out.println(person1);
Object o = personClass.newInstance();
System.out.println(o);
獲取成員方法們
Method[] getMethods()
Method getMethod(String name, 類<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, 類<?>... parameterTypes)
案例:
//0.獲取Person的Class對象
Class personClass = Person.class;
//獲取指定名稱的方法
Method eat_method = personClass.getMethod("eat");
Person p = new Person();
//執(zhí)行方法
eat_method.invoke(p);
Method eat_method2 = personClass.getMethod("eat", String.class);
//執(zhí)行方法
eat_method2.invoke(p,"飯");
System.out.println("-----------------");
//獲取所有public修飾的方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
String name = method.getName();
System.out.println(name);
//method.setAccessible(true);
}
//獲取類名
String className = personClass.getName();
System.out.println(className);//com.zjq.javabase.base25.domain.Person
獲取全類名
String getName()
Field:成員變量
操作:
1. 設(shè)置值
void set(Object obj, Object value)
2. 獲取值
get(Object obj)
3. 忽略訪問權(quán)限修飾符的安全檢查
setAccessible(true):暴力反射
Constructor:構(gòu)造方法
創(chuàng)建對象:
T newInstance(Object... initargs)
如果使用空參數(shù)構(gòu)造方法創(chuàng)建對象,操作可以簡化:Class對象的newInstance方法
Method:方法對象
執(zhí)行方法:
Object invoke(Object obj, Object... args)
獲取方法名稱:
String getName:獲取方法名
案例
需求:寫一個"框架",不能改變該類的任何代碼的前提下,可以幫我們創(chuàng)建任意類的對象,并且執(zhí)行其中任意方法
實(shí)現(xiàn):
1. 配置文件
2. 反射
步驟:
1. 將需要創(chuàng)建的對象的全類名和需要執(zhí)行的方法定義在配置文件中
2. 在程序中加載讀取配置文件
3. 使用反射技術(shù)來加載類文件進(jìn)內(nèi)存
4. 創(chuàng)建對象
5. 執(zhí)行方法
代碼:
pro.properties文件內(nèi)容如下:
className=com.zjq.javabase.base25.domain.Student methodName=sleep
Student類:
public class Student {
public void sleep() {
System.out.println("sleep...");
}
}
反射操作:
//1.加載配置文件
//1.1創(chuàng)建Properties對象
Properties pro = new Properties();
//1.2加載配置文件,轉(zhuǎn)換為一個集合
//1.2.1獲取class目錄下的配置文件
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("pro.properties");
pro.load(is);
//2.獲取配置文件中定義的數(shù)據(jù)
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加載該類進(jìn)內(nèi)存
Class cls = Class.forName(className);
//4.創(chuàng)建對象
Object obj = cls.newInstance();
//5.獲取方法對象
Method method = cls.getMethod(methodName);
//6.執(zhí)行方法
method.invoke(obj);
到此這篇關(guān)于Java框架設(shè)計(jì)靈魂之反射的示例詳解的文章就介紹到這了,更多相關(guān)Java反射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文詳解如何使用線程池來優(yōu)化我們的應(yīng)用程序
線程池是一種工具,但并不是適用于所有場景。在使用線程池時,我們需要根據(jù)應(yīng)用程序的性質(zhì)、計(jì)算資源的可用性和應(yīng)用程序的需求進(jìn)行適當(dāng)?shù)呐渲谩1疚闹饕榻B了如何使用線程池來優(yōu)化我們的應(yīng)用程序,需要的可以參考一下2023-04-04
SpringBoot與單元測試JUnit的結(jié)合操作
這篇文章主要介紹了SpringBoot與單元測試JUnit的結(jié)合操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Java實(shí)現(xiàn)多線程輪流打印1-100的數(shù)字操作
這篇文章主要介紹了Java實(shí)現(xiàn)多線程輪流打印1-100的數(shù)字操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Java使用Lambda表達(dá)式查找list集合中是否包含某值問題
Java使用Lambda表達(dá)式查找list集合中是否包含某值的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
使用Java實(shí)現(xiàn)查找并移除字符串中的Emoji
Emoji 實(shí)際上是 UTF-8 (Unicode) 字符集上的特殊字符,這篇文章主要介紹了如何使用Java實(shí)現(xiàn)查找并移除字符串中的Emoji,感興趣的可以了解下2024-03-03
帶有@Transactional和@Async的循環(huán)依賴問題的解決
這篇文章主要介紹了帶有@Transactional和@Async的循環(huán)依賴問題的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
maven profile實(shí)現(xiàn)多環(huán)境配置的示例
這篇文章主要介紹了maven profile實(shí)現(xiàn)多環(huán)境配置的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01

