咱們在第一次接觸反射的時候,總會有個很大的疑問,反射看起來好麻煩啊,各類get.get,他究竟有什麼好處,能用來作什麼呢?java
咱們先來看一下《編程思想》這本書中是怎麼說的.sql
RTTI和反射之間真正的區別只在於,對RTTI來講,編譯器在在編譯時打開和檢查.class文件.(換句話說,咱們能夠用"普通"方式調用對象的全部方法).對於反射機制來講,.class文件在編譯時是不可獲取的,因此在運行時打開和檢查.class文件。 --《編程思想》數據庫
這段話看起來很叼的樣子,有點雲裏霧裏的,首先RTTI的意思就是以普通的方式來建立對象,調用方法,就是咱們經常使用的new
關鍵字。這段話的意思簡化版就是:編譯器將.java文件編譯成.class文件以後,普通方式建立的對象就不能再變了,我只能選擇是運行仍是不運行這個.class文件。是否是感受很僵硬,假如如今我有個寫好的程序已經放在了服務器上,天天供人家來訪問,這時候Mysql數據庫宕掉了,改用Oracle,這時候該怎麼怎麼辦呢?假如沒有反射的話,咱們是否是得修改代碼,將Mysql驅動改成Oracle驅動,從新編譯運行,再放到服務器上。是否是很麻煩,還影響用戶的訪問。編程
假如咱們使用反射Class.forName()來加載驅動,只須要修改配置文件就能夠動態加載這個類,Class.forName()生成的結果在編譯時是不可知的,只有在運行的時候才能加載這個類,換句話說,此時咱們是不須要將程序停下來,只須要修改配置文件裏面的信息就能夠了。這樣當有用戶在瀏覽器訪問這個網站時,都不會感受到服務器程序程序發生了變化。瀏覽器
因此在《Mybatis技術原理與實戰》是這麼說反射的好處的。服務器
配置性大大提升,如同Spring IOC容器,給不少配置設置參數,使得java應用程序可以順利跑起來,大大提升了Java的靈活性和可配置性,下降模塊間的耦合。--《Mybatis技術原理與實戰》框架
相應的實例性能
Eclipse的代碼自動補全就是利用了反射原理動態的加載要展現的方法,由於反射會影響性能,因此開了自動補全剛開始的時候會卡一下,主要仍是我電腦性能不行。網站
反射的進階ui
在JDK動態代理中能夠利用反射直接獲取到接口的方法來執行,從而能夠將代理類要處理的代碼抽象出來造成統一的接口。
ClassLoader:
ClassLoader
就是遵循雙親委派模型最終調用啓動類加載器的類加載器,實現的功能是「經過一個類的全限定名來獲取描述此類的二進制字節流」,獲取到二進制流後放到JVM中。
例如ClassLoader.getSystemClassLoader().loadClass("com.test.mytest.ClassForName");
是不會初始化類的。
Class.forName():
Class.forName()
方法實際上也是調用的CLassLoader來實現的。
Class.forName(String name, boolean initialize,ClassLoader loader)
方法來手動選擇在加載類的時候是否要對類進行初始化。
應用場景:
1. 在咱們熟悉的Spring框架中的IOC的實現就是使用的ClassLoader。
2. 使用JDBC時一般是使用Class.forName()方法來加載數據庫鏈接驅動。這是由於在JDBC規範中明確要求Driver(數據庫驅動)類必須向DriverManager註冊本身
public class Driver extends NonRegisteringDriver implements java.sql.Driver { // Register ourselves with the DriverManager static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } public Driver() throws SQLException { // Required for Class.forName().newInstance() } }
Class.forName()
會初始化類,因此自動加載static
代碼段,從而註冊本身。