1、類的編譯和運行簡易過程: java的源碼文件(也稱為編譯單元,以.java為尾碼的文件) ↓ 文件內最多只能有一個public修飾的類,否則編譯器報錯;某個類被public修飾,該類名必需與文件名稱一致; java的位元組碼文件(以.class為尾碼的文件) ↓ 源碼文件經過編譯器編譯後產生的位元組 ...
1、類的編譯和運行簡易過程:
- java的源碼文件(也稱為編譯單元,以.java為尾碼的文件)
↓ 文件內最多只能有一個public修飾的類,否則編譯器報錯;某個類被public修飾,該類名必需與文件名稱一致;
- java的位元組碼文件(以.class為尾碼的文件)
↓ 源碼文件經過編譯器編譯後產生的位元組碼文件,源碼文件中的每個類都會產生一個與類名相同的位元組碼文件
- java虛擬機解析位元組碼文件
載入.class文件,在記憶體里保持Class對象,它被用來創建這個類的所有對象。
2、獲取Class對象的途徑
- Class.forName()
- 已知某個對象w,通過w.getClass()方法獲取,該方法在Object中
- 普通的類、介面、數組、基本數據類型,可以通過 .class的形式獲取,如char.class、Petty.class
3、反射--運行時的類型信息
什麼是反射:程式在運行時候,可以通過類型信息獲取類的域、方法、構造器等細節,通過java的反射API可以調用這些域、方法、構造器等
反射的API在java.lang.reflect類庫,Class類的實例表示正在運行的 Java 應用程式中的類和介面,因此可以獲取Field、Method、Constructor類的對象等信息
4、反射應用--動態代理(jdk版)
- 先看看靜態代理:
package com.leixingxinxi; public class Main {
public static void main(String[] args) { TestFace testFace=new Person1(); new Persion2(testFace).testDo(); } } interface TestFace{ void testDo(); } class Person1 implements TestFace{ public void testDo() { System.out.println("去買一杯咖啡..."); } } class Persion2 implements TestFace{ TestFace testFace; public Persion2(TestFace testFace){ this.testFace=testFace; } public void testDo() {
//方法前的操作 testFace.testDo();
//方法後的操作 } }
直接調用方法:可以新建對象Persion1並執行testDo()方法,能夠得到一致的結果;------>>>main 讓 persion1去買一杯咖啡;
使用靜態代理:被代理類和代理類都實現了同一個介面,將被代理類的對象註入代理類的對象域中,在代理類中重寫的方法里通過被代理類對象調用對應的方法,實際使用不直接使用被代理類的方法,而是通過代理類的對象調用覆蓋的方法;那麼在代理類中調用的方法里,真正去調用被代理類的方法前後可以做一些操作------>>>main 告訴persion2 去買咖啡,persion2通知persion1去買一杯咖啡
- 動態代理(jdk版):動態的創建了代理對象,並動態的處理對所代理的方法的調用。
package com.leixingxinxi; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Main { public static void main(String[] args) { TestFace proxy= (TestFace) Proxy.newProxyInstance(Persion1.class.getClassLoader(),Persion1.class.getInterfaces(), new MyInvocationHandler(new Persion1())); proxy.testDo(); } } interface TestFace{ void testDo(); } class Persion1 implements TestFace{ public void testDo() { System.out.println("去買一杯咖啡..."); } } class MyInvocationHandler implements InvocationHandler{ private TestFace testFace; public MyInvocationHandler(TestFace testFace){ this.testFace=testFace; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //調用被代理對象的方法前的業務 System.out.println("當前調用的方法為:"+method.getName()); //調用被代理對象方法 method.invoke(testFace); //調用被代理對象的方法後的業務 System.out.println("被代理的方法調用結束"); return null; } }
調用過程:通過代理對象proxy調用代理方法時候,實際會去調用MyInvocationHandler 對象的invoke方法,該方法內部會調用Method的invoke方法真正去執行被代理對象的方法體