Java的動態(tài)代理和靜態(tài)代理及反射常用API詳解
JDK動態(tài)代理
我們看下JDK動態(tài)代理的實現(xiàn)步驟:
第一步:創(chuàng)建接口,JDK動態(tài)代理基于接口實現(xiàn),所以接口必不可少(準(zhǔn)備工作)
第二步:實現(xiàn)InvocationHandler接口,重寫invoke方法(準(zhǔn)備工作)
第三步:調(diào)用Proxy的靜態(tài)方法newProxyInstance方法生成代理實例(生成實例時需要提供類加載器,我們可以使用接口類的加載器即可)
第四步:使用新生成的代理實例調(diào)用某個方法實現(xiàn)功能。
我們的動態(tài)代理實現(xiàn)過程中根本沒有涉及到真實類實例。
靜態(tài)代理
package ceshi1;
public interface Iuser {
void eat(String s);
}
package ceshi1;
public class UserImpl implements Iuser {
@Override
public void eat(String s) {
System.out.println("我要吃"+s);
}
}
package ceshi1;
public class UserProxy implements Iuser {
private Iuser user = new UserImpl();
@Override
public void eat(String s) {
System.out.println("靜態(tài)代理前置內(nèi)容");
user.eat(s);
System.out.println("靜態(tài)代理后置內(nèi)容");
}
}
package ceshi1;
public class ProxyTest {
public static void main(String[] args) {
UserProxy proxy = new UserProxy();
proxy.eat("蘋果");
}
}動態(tài)代理
package ceshi1;
public interface Iuser {
void eat(String s);
}
package ceshi1;
public class UserImpl implements Iuser {
@Override
public void eat(String s) {
System.out.println("我要吃"+s);
}
}
package ceshi1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler {
private Object object;//用于接收具體實現(xiàn)類的實例對象
//使用帶參數(shù)的構(gòu)造器來傳遞具體實現(xiàn)類的對象
public DynamicProxy(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("前置內(nèi)容");
method.invoke(object, args);
System.out.println("后置內(nèi)容");
return null;
}
}
package ceshi1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
Iuser user = new UserImpl();
InvocationHandler h = new DynamicProxy(user);
Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[]{Iuser.class}, h);
proxy.eat("蘋果");
}
}
反射
JDK 提供的反射 API 進行反射調(diào)用:
Class clz = Class.forName("com.chenshuyi.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);
一般情況下我們使用反射獲取一個對象的步驟:
獲取類的 Class 對象實例
Class clz = Class.forName("com.zhenai.api.Apple");根據(jù) Class 對象實例獲取 Constructor 對象
Constructor appleConstructor = clz.getConstructor();
使用 Constructor 對象的 newInstance 方法獲取反射類對象
Object appleObj = appleConstructor.newInstance();
而如果要調(diào)用某一個方法,則需要經(jīng)過下面的步驟:
獲取方法的 Method 對象
Method setPriceMethod = clz.getMethod("setPrice", int.class);
利用 invoke 方法調(diào)用方法
setPriceMethod.invoke(appleObj, 14);
反射常用API
在 Java API 中,獲取 Class 類對象有三種方法:
第一種,使用 Class.forName 靜態(tài)方法。當(dāng)你知道該類的全路徑名時,你可以使用該方法獲取 Class 類對象。
Class clz = Class.forName("java.lang.String");第二種,使用 .class 方法。
這種方法只適合在編譯前就知道操作的 Class。
Class clz = String.class;
第三種,使用類對象的 getClass() 方法。
String str = new String("Hello");
Class clz = str.getClass();通過反射創(chuàng)建類對象
通過反射創(chuàng)建類對象主要有兩種方式:通過 Class 對象的 newInstance() 方法、通過 Constructor 對象的 newInstance() 方法。
第一種:通過 Class 對象的 newInstance() 方法。
Class clz = Apple.class; Apple apple = (Apple)clz.newInstance();
第二種:通過 Constructor 對象的 newInstance() 方法
Class clz = Apple.class; Constructor constructor = clz.getConstructor(); Apple apple = (Apple)constructor.newInstance();
通過 Constructor 對象創(chuàng)建類對象可以選擇特定構(gòu)造方法,而通過 Class 對象則只能使用默認(rèn)的無參數(shù)構(gòu)造方法。下面的代碼就調(diào)用了一個有參數(shù)的構(gòu)造方法進行了類對象的初始化。
Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("紅富士", 15);
我們通過 Class 對象的 getFields() 方法可以獲取 Class 類的屬性,但無法獲取私有屬性。
Class clz = Apple.class;
Field[] fields = clz.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
而如果使用 Class 對象的 getDeclaredFields() 方法則可以獲取包括私有屬性在內(nèi)的所有屬性:
Class clz = Apple.class;
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
}
到此這篇關(guān)于Java的動態(tài)代理和靜態(tài)代理及反射常用API詳解的文章就介紹到這了,更多相關(guān)Java動態(tài)代理和反射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決idea中svn提交時performing vcs refresh時間很長的問題
這篇文章主要介紹了解決idea中svn提交時performing vcs refresh時間很長的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Java設(shè)計模式之Template?Pattern模板模式詳解
這篇文章主要介紹了Java設(shè)計模式之Template?Pattern模板模式詳解,模板模式(Template?Pattern)行為型模式之一,抽象父類定義一個操作中的算法的骨架,而將一些步驟延遲到子類中,需要的朋友可以參考下2023-10-10
Java零基礎(chǔ)教程之do-while循環(huán)語句實例
Java中的do-while循環(huán)是一種后測試循環(huán)語句,它類似于while循環(huán),但它先執(zhí)行循環(huán)體中的代碼,然后再進行條件判斷,無論條件是否滿足,至少會執(zhí)行一次循環(huán)體中的代碼,這篇文章主要給大家介紹了關(guān)于Java零基礎(chǔ)教程之do-while循環(huán)語句的相關(guān)資料,需要的朋友可以參考下2024-09-09
Java音頻處理之音頻流轉(zhuǎn)音頻文件和獲取音頻播放時長詳解
這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)音頻流轉(zhuǎn)音頻文件和獲取音頻播放時長功能,文中的示例代碼簡潔易懂,有需要的小伙伴可以了解下2025-07-07

