java反射機制

來源:互聯網
上載者:User

標籤:ram   解析   access   檔案中   調用   gen   string   obj   div   

java反射機制

java語言允許通過程式化的方式間接對Class的對象執行個體操作,Class檔案由類載入器裝載後,在JVM中將形成一份描述class結構的元資訊對象,通過該元資訊對象可以獲知class的結構資訊,通過該源資訊對象可以獲知class的結構資訊,如建構函式、屬性和方法等

舉一個反射的小例子:

car類主要包含三個屬性,和一個無參建構函式與一個帶參建構函式

public class Car {  private String brand;  private String color;  private int maxspeed;    public Car() {    System.out.println("init car");  }  public Car(String brand, String color, int maxspeed) {    this.brand = brand;    this.color = color;    this.maxspeed = maxspeed;  }    public void introduce(){    System.out.println("品牌:"+brand+"顏色:"+color+"最大速度:"+maxspeed);  }  public String getBrand() {    return brand;  }  public void setBrand(String brand) {    this.brand = brand;  }  public String getColor() {    return color;  }  public void setColor(String color) {    this.color = color;  }  public int getMaxspeed() {    return maxspeed;  }  public void setMaxspeed(int maxspeed) {    this.maxspeed = maxspeed;  }}

這裡利用反射擷取構造器執行個體化對象

public class ReflectTest {  //通過預設構造方法初始化car對象  public static Car initDefaultConst() throws Throwable{    //1.通過類裝載器擷取Car類對象    ClassLoader loader = Thread.currentThread().getContextClassLoader();    Class clazz =loader.loadClass("com.xiongda.spring.reflect.Car");        //2.擷取類的預設構造器對象並執行個體化Car    Constructor cons =clazz.getDeclaredConstructor(null);    Car car =(Car) cons.newInstance();        //3.通過反射方法設定屬性    Method setBrand =clazz.getMethod("setBrand", String.class);    setBrand.invoke(car, "平治");    Method setColor =clazz.getMethod("setColor", String.class);    setColor.invoke(car, "黑色");    Method setMaxspeed =clazz.getMethod("setMaxspeed", int.class);    setMaxspeed.invoke(car, 200);        return car;  }  //通過帶參構造方法初始化car對象  public static Car initParamConst() throws Throwable{  //1.通過類裝載器擷取Car類對象    ClassLoader loader = Thread.currentThread().getContextClassLoader();    Class clazz =loader.loadClass("com.xiongda.spring.reflect.Car");        //2.擷取類的帶參構造器對象並執行個體化Car    Constructor cons =clazz.getDeclaredConstructor(String.class,String.class,int.class);    Car car =(Car) cons.newInstance("寶馬","紅色",180);        return car;  }      public static void main(String[] args) throws Throwable {    Car car1 =ReflectTest.initDefaultConst();    Car car2 =ReflectTest.initParamConst();    car1.introduce();    car2.introduce();  }}

 

在傳統方法中,我們一般是使用建構函式設定屬性或者set方法設定屬性

 

類裝載器ClassLoader
類裝載器就是尋找類的位元組碼檔案並構造出類在JVM內部表示的對象組件,主要工作由ClassLoader及其子類負責,ClassLoader是一個重要的java運行時系統組件,它負責在運行時尋找和裝入class位元組碼檔案

工作機制:
1.裝載:尋找和匯入class檔案
2.連結:執行校正,準備和解析步驟
3.初始化:對類的靜態變數、靜態代碼塊執行初始化工作

重要方法:
1.Class loadClass(String name)
2.Class defineClass(String name,byte[] b, int off, int len)
3.Class findSystemClass(String name)
4.Class findLoadedClass(String name)
5.ClassLoader getParent()

 

Class反射對象描述類語義結構,可以從Class對象中擷取建構函式,成員變數,方法等類元素的反射對象,並以編程的方式通過這些反射對象對目標對象進行操作。這些反射對象類在java.reflect包中定義

 

三個最主要的反射類:
Constructor
Method
Field

 

在Spring中,通過IOC可以將實作類別、參數資訊等配置在其對應的設定檔中,那麼當需要更改實作類別或參數資訊時,,只需要修改設定檔即可,我們還可以對其對象所需要的其它對象進行注入,這種注入都是在設定檔中做的

 

Spring的IOC的實現原理利用的就是java的反射機制,Spring的工廠類會幫我們完成設定檔的讀取、利用反射機制注入對象等工作,我們可以通過bean的名稱擷取對應的對象

基本的javabean

public class JavaBean {  private String username;  private String password;  public String getUsername() {    return username;  }  public void setUsername(String username) {    this.username = username;  }  public String getPassword() {    return password;  }  public void setPassword(String password) {    this.password = password;  }  }

讀取設定檔,然後通過Java反射機制執行個體化javabean

public class BeanFactory {  private Map<String, Object> beanMap = new HashMap<>();    /**   * bean工廠的初始化   * @param xml   */  public void init(String sxml){    InputStream ins= null;    Document doc = null;      try {        //1.建立讀取設定檔的reader對象        SAXReader reader =new SAXReader();        //2.擷取當前線程中的類裝載器對象        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();        //3.從class目錄下擷取指定的xml檔案         ins = classLoader.getResourceAsStream(sxml);         if(ins == null){           System.out.println("擷取流失敗");         }         doc = reader.read(ins);        Element root = doc.getRootElement();        Element foo;                //4.遍曆xml檔案中的Bean執行個體        for(Iterator i =root.elementIterator("bean");i.hasNext();){          foo=(Element) i.next();                    //5.針對每一個bean執行個體,擷取bean的屬性id和class          Attribute id =foo.attribute("id");          Attribute cls=foo.attribute("class");                              //6.利用java反射機制,通過class的名稱擷取class對象          Class bean = Class.forName(cls.getText());                    //7.擷取對應class的資訊          java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);                    //8.擷取其屬性描述          java.beans.PropertyDescriptor pd[] =info.getPropertyDescriptors();                    //9.建立一個對象,並在接下來的代碼中為對象的屬性賦值          Object obj = bean.newInstance();                    //10.遍曆該bean的property屬性          for(Iterator ite = foo.elementIterator("property");ite.hasNext();){            Element foo2 = (Element) ite.next();                        //11.擷取該property的name屬性            Attribute name = foo2.attribute("name");            String value = null;                        //12.擷取該property的子項目value的值            for(Iterator ite1 =foo2.elementIterator("value");ite1.hasNext();){              Element node = (Element) ite1.next();              value = node.getText();                           break;            }                        //13.利用java的反射機制調用對象的某個set方法,並將值設定進去            for(int k=0;k<pd.length;k++){              if(pd[k].getName().equalsIgnoreCase(name.getText())){                Method mset = null;                mset = pd[k].getWriteMethod();                mset.invoke(obj, value);              }            }          }                    //14.將對象放入beanMap中,其中key為id值,value為對象          beanMap.put(id.getText(), obj);        }      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException          | InvocationTargetException | DocumentException | IntrospectionException e) {        // TODO Auto-generated catch block        if(doc ==null){          System.out.println("擷取失敗");        }        e.printStackTrace();      }   }    public Object getBean(String beanName){    Object obj =beanMap.get(beanName);    return obj;  }    public static void main(String[] args) throws Throwable {    BeanFactory factory = new BeanFactory();    factory.init("config.xml");    JavaBean  javabean =(JavaBean)factory.getBean("javaBean");    System.out.println("username  "+javabean.getUsername());    System.out.println("password  "+javabean.getPassword());      }}

xml檔案

<?xml version="1.0" encoding="UTF-8"?><beans>    <bean id="javaBean" class="com.xiongda.spring.reflect.JavaBean">        <property name="username">            <value>極客學院</value>        </property>        <property name="password">            <value>1234567890</value>        </property>    </bean></beans>

注意:如果你是用eclipse的話,你這個xml檔案一定要放在bin目錄裡面,否則會報出一個null 指標異常。但是後來我發現,用IDEA的話就不存在這個問題。(解決這東西花了不少時間,至今還未明白為啥會存在這種區別)

(備忘:使用SAXReader需要導包dom4j)

java反射機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.