在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>java源碼下載>

實(shí)例分析講解java中的反射機(jī)制

大小:0.2 MB 人氣: 2017-09-27 需要積分:0

  動(dòng)態(tài)語(yǔ)言

  動(dòng)態(tài)語(yǔ)言,是指程序在運(yùn)行時(shí)可以改變其結(jié)構(gòu):新的函數(shù)可以被引進(jìn),已有的函數(shù)可以被刪除等在結(jié)構(gòu)上的變化。比如眾所周知的ECMA(Java)便是一個(gè)動(dòng)態(tài)語(yǔ)言。除此之外如Ruby、Python等也都屬于動(dòng)態(tài)語(yǔ)言,而C、C++等語(yǔ)言則不屬于動(dòng)態(tài)語(yǔ)言。(引自: 百度百科)

  var execString = “alert(Math.floor(Math.random()*10));”; eval( execString);Class 反射機(jī)制

  指的是可以于運(yùn)行時(shí)加載,探知和使用編譯期間完全未知的類。

  程序在運(yùn)行狀態(tài)中, 可以動(dòng)態(tài)加載一個(gè)只有名稱的類, 對(duì)于任意一個(gè)已經(jīng)加載的類,都能夠知道這個(gè)類的所有屬性和方法; 對(duì)于任意一個(gè)對(duì)象,都能調(diào)用他的任意一個(gè)方法和屬性;

  加載完類之后, 在堆內(nèi)存中會(huì)產(chǎn)生一個(gè)Class

  類型的對(duì)象(一個(gè)類只有一個(gè)Class對(duì)象), 這個(gè)對(duì)象包含了完整的類的結(jié)構(gòu)信息,而且這個(gè)Class對(duì)象就像一面鏡子,透過(guò)這個(gè)鏡子看到類的結(jié)構(gòu),所以被稱之為:反射。

  Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions(維度)。 The primitive Java types (boolean, byte, char, short, int, long, float, anddouble), and the keyword void are also represented as Class objects.

  - 每個(gè)類被加載進(jìn)入內(nèi)存之后,系統(tǒng)就會(huì)為該類生成一個(gè)對(duì)應(yīng)的java.lang.Class

  對(duì)象,通過(guò)該Class

  對(duì)象就可以訪問(wèn)到JVM中的這個(gè)類。

  Class對(duì)象的獲取

  - 對(duì)象的getClass()方法;

  - 類的.class(最安全/性能最好)屬性;

  - 運(yùn)用Class.forName(String className)動(dòng)態(tài)加載類,className需要是類的全限定名(最常用)。

  從Class中獲取信息

  Class類提供了大量的實(shí)例方法來(lái)獲取該Class對(duì)象所對(duì)應(yīng)的詳細(xì)信息,Class類大致包含如下方法,其中每個(gè)方法都包含多個(gè)重載版本,因此我們只是做簡(jiǎn)單的介紹,詳細(xì)請(qǐng)參考JDK文檔

  獲取類內(nèi)信息

  實(shí)例分析講解java中的反射機(jī)制

  一些判斷類本身信息的方法

  實(shí)例分析講解java中的反射機(jī)制

  使用反射生成并操作對(duì)象:

  Method Constructor Field這些類都實(shí)現(xiàn)了java.lang.reflect.Member接口,程序可以通過(guò)Method對(duì)象來(lái)執(zhí)行相應(yīng)的方法,通過(guò)Constructor對(duì)象來(lái)調(diào)用對(duì)應(yīng)的構(gòu)造器創(chuàng)建實(shí)例,通過(guò)Filed對(duì)象直接訪問(wèn)和修改對(duì)象的成員變量值。

  創(chuàng)建對(duì)象

  通過(guò)反射來(lái)生成對(duì)象的方式有兩種:

  - 使用Class對(duì)象的newInstance()方法來(lái)創(chuàng)建該Class對(duì)象對(duì)應(yīng)類的實(shí)例(這種方式要求該Class對(duì)象的對(duì)應(yīng)類有默認(rèn)構(gòu)造器)。

  - 先使用Class對(duì)象獲取指定的Constructor對(duì)象, 再調(diào)用Constructor對(duì)象的newInstance()方法來(lái)創(chuàng)建該Class對(duì)象對(duì)應(yīng)類的實(shí)例(通過(guò)這種方式可以選擇指定的構(gòu)造器來(lái)創(chuàng)建實(shí)例)。

  通過(guò)第一種方式來(lái)創(chuàng)建對(duì)象比較常見(jiàn), 像Spring這種框架都需要根據(jù)配置文件(如applicationContext.xml)信息來(lái)創(chuàng)建Java對(duì)象,從配置文件中讀取的只是某個(gè)類的全限定名字符串,程序需要根據(jù)該字符串來(lái)創(chuàng)建對(duì)應(yīng)的實(shí)例,就必須使用默認(rèn)的構(gòu)造器來(lái)反射對(duì)象。下面我們就模擬Spring實(shí)現(xiàn)一個(gè)簡(jiǎn)單的對(duì)象池, 該對(duì)象池會(huì)根據(jù)文件讀取key-value對(duì), 然后創(chuàng)建這些對(duì)象, 并放入Map中。

  配置文件

  { “ objects”: [ { “id”: “id1”, “class”: “com.fq.domain.User”}, { “id”: “id2”, “class”:“com.fq.domain.Bean”} ] }

  ObjectPool

  /** * Created by jifang on 15/12/31. */publicclassObjectPool{privateMap《String, Object》 pool; privateObjectPool(Map《String, Object》 pool) { this.pool = pool; } privatestaticObjectgetInstance(String className) throwsClassNotFoundException, IllegalAccessException, InstantiationException { returnClass.forName(className).newInstance(); }privatestaticJSONArray getObjects(String config) throwsIOException { Reader reader =newInputStreamReader(ClassLoader.getSystemResourceAsStream(config));returnJSONObject.parseObject(CharStreams.toString(reader)).getJSONArray( “objects”); } // 根據(jù)指定的JSON配置文件來(lái)初始化對(duì)象池publicstaticObjectPool init(String config) {try{ JSONArray objects = getObjects(config); ObjectPool pool = newObjectPool(newHashMap《String, Object》()); if(objects != null&& objects.size() != 0) { for( inti = 0; i 《 objects.size(); ++i) { JSONObject object = objects.getJSONObject(i); if(object == null|| object.size() == 0) { continue; } String id = object.getString( “id”); String className = object.getString( “class”); pool.putObject(id, getInstance(className)); } } returnpool; }catch(IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { thrownewRuntimeException(e); } } publicObjectgetObject(String id) { returnpool.get(id); } publicvoidputObject(String id, Object object) { pool.put(id, object); } publicvoidclear() { pool.clear(); } }

  Client

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassClient{@Testpublicvoidclient() { ObjectPool pool = ObjectPool.init(“config.json”); User user = (User) pool.getObject( “id1”); System.out.println(user); Bean bean = (Bean) pool.getObject( “id2”); System.out.println(bean); } }

  User

  publicclass User { privateint id; privateStringname; privateStringpassword; publicint getId() { returnid; } publicvoidsetId( Integerid) { this .id =id; } publicStringgetName() { returnname; } publicvoidsetName( Stringname) { this .name =name; } publicStringgetPassword() {returnpassword; } publicvoidsetPassword( Stringpassword) { this .password =password; } @Override publicStringtoString() { return“User{”+“id=”+id +“, name=‘”+name +’/‘’ + “, password=‘” + password + ’/‘’ + ‘}’; } }

  Bean

  publicclass Bean { privateBoolean usefull; privateBigDecimal rate; privateStringname;publicBoolean getUsefull() { returnusefull; } publicvoidsetUsefull(Boolean usefull) { this.usefull =usefull; } publicBigDecimal getRate() { returnrate; } publicvoidsetRate(BigDecimal rate) { this .rate =rate; } publicStringgetName() { returnname; } publicvoidsetName(Stringname) { this .name =name; } @Override publicStringtoString() {return“Bean{”+“usefull=”+usefull +“, rate=”+rate +“, name=‘”+name +’/‘’ + ‘} ’; } }

  注意: 需要在pom.xml中添加如下依賴:

  《dependency》《groupId》com.alibaba 《/groupId》《artifactId》fastjson 《/artifactId》《version》1.2.7 《/version》《/dependency》《dependency》《groupId》com.google.guava《/groupId》《artifactId》guava 《/artifactId》《version》18.0 《/version》《/dependency》

  調(diào)用方法

  當(dāng)獲取到某個(gè)類對(duì)應(yīng)的Class對(duì)象之后, 就可以通過(guò)該Class對(duì)象getMethod來(lái)獲取一個(gè)Method數(shù)組或Method對(duì)象。每個(gè)Method對(duì)象對(duì)應(yīng)一個(gè)方法,在獲得Method對(duì)象之后,就可以通過(guò)調(diào)用invoke方法來(lái)調(diào)用該Method對(duì)象對(duì)應(yīng)的方法。

  @CallerSensitive public Object invoke(Object obj, Object.。。 args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 。。.}

  下面我們對(duì)上面的對(duì)象池加強(qiáng):可以看到Client獲取到的對(duì)象的成員變量全都是默認(rèn)值,既然我們已經(jīng)使用了JSON這么優(yōu)秀的工具,我們又學(xué)習(xí)了動(dòng)態(tài)調(diào)用對(duì)象的方法,那么我們就通過(guò)配置文件來(lái)給對(duì)象設(shè)置值(在對(duì)象創(chuàng)建時(shí)), 新的配置文件形式如下:

  { “ objects”: [ { “id”: “id1”, “class”: “com.fq.domain.User”, “fields”: [ { “name”: “id”, “value”:101}, { “name”: “name”, “value”: “feiqing”}, { “name”: “password”, “value”:“ICy5YqxZB1uWSwcVLSNLcA==”} ] }, { “id”: “id2”, “class”: “com.fq.domain.Bean”, “fields”:[ { “name”: “usefull”, “value”: true}, { “name”: “rate”, “value”: 3.14}, { “name”: “name”, “value”: “bean-name”} ] }, { “id”: “id3”, “class”: “com.fq.domain.ComplexBean”, “fields”: [ { “name”: “name”, “value”: “complex-bean-name”}, { “name”: “refBean”, “ref”: “id2”} ] } ] }

  其中fields代表該Bean所包含的屬性, name為屬性名稱, value為屬性值(屬性類型為JSON支持的類型), ref代表引用一個(gè)對(duì)象(也就是屬性類型為Object,但是一定要引用一個(gè)已經(jīng)存在了的對(duì)象)

  /** *@authorjifang *@since15/12/31下午4:00 */publicclassObjectPool{privateMap《String, Object》 pool; privateObjectPool(Map《String, Object》 pool) { this.pool = pool; }privatestaticJSONArray getObjects(String config) throwsIOException { Reader reader =newInputStreamReader(ClassLoader.getSystemResourceAsStream(config));returnJSONObject.parseObject(CharStreams.toString(reader)).getJSONArray( “objects”); } privatestaticObject getInstance(String className, JSONArray fields)throwsClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { // 配置的ClassClass《?》 clazz = Class.forName(className); // 目標(biāo)Class的實(shí)例對(duì)象Object targetObject = clazz.newInstance(); if(fields != null&& fields.size() != 0) { for( inti = 0; i 《 fields.size(); ++i) { JSONObject field = fields.getJSONObject(i); // 需要設(shè)置的成員變量名String fieldName = field.getString( “name”); // 需要設(shè)置的成員變量的值Object fieldValue; if(field.containsKey(“value”)) { fieldValue = field.get( “value”); } elseif(field.containsKey( “ref”)) { String refBeanId = field.getString( “ref”); fieldValue = OBJECTPOOL.getObject(refBeanId); }else{ thrownewRuntimeException( “neither value nor ref”); } String setterName = “set”+ fieldName.substring( 0, 1).toUpperCase() + fieldName.substring( 1); // 需要設(shè)置的成員變量的setter方法Method setterMethod = clazz.getMethod(setterName, fieldValue.getClass()); // 調(diào)用setter方法將值設(shè)置進(jìn)去setterMethod.invoke(targetObject, fieldValue); } } returntargetObject; } privatestaticObjectPool OBJECTPOOL; // 創(chuàng)建一個(gè)對(duì)象池的實(shí)例(保證是多線程安全的)privatestaticvoidinitSingletonPool() { if(OBJECTPOOL ==null) { synchronized(ObjectPool.class) { if(OBJECTPOOL == null) { OBJECTPOOL =newObjectPool( newConcurrentHashMap《String, Object》()); } } } } // 根據(jù)指定的JSON配置文件來(lái)初始化對(duì)象池publicstaticObjectPool init(String config) { // 初始化poolinitSingletonPool(); try{ JSONArray objects = getObjects(config); for( inti = 0; objects != null&& i 《 objects.size(); ++i) { JSONObject object = objects.getJSONObject(i); if(object == null|| object.size() == 0) { continue; } String id = object.getString( “id”); String className = object.getString( “class”); // 初始化bean并放入池中OBJECTPOOL.putObject(id, getInstance(className, object.getJSONArray( “fields”))); }returnOBJECTPOOL; } catch(IOException | ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { thrownewRuntimeException(e); } } publicObjectgetObject(String id) { returnpool.get(id); } publicvoidputObject(String id, Object object) { pool.put(id, object); } publicvoidclear() { pool.clear(); } }

  Client

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassClient{@Testpublicvoidclient() { ObjectPool pool = ObjectPool.init(“config.json”); User user = (User) pool.getObject( “id1”); System.out.println(user); Bean bean = (Bean) pool.getObject( “id2”); System.out.println(bean); ComplexBean complexBean = (ComplexBean) pool.getObject( “id3”); System.out.println(complexBean); } }

  ComplexBean

  publicclass ComplexBean { privateStringname; privateBean refBean;publicStringgetName() { returnname; } publicvoidsetName( Stringname) { this .name=name; } publicBean getRefBean() { returnrefBean; } publicvoidsetRefBean(Bean refBean) { this .refBean =refBean; } @Override publicStringtoString() {return“ComplexBean{”+“name=‘”+name +’/‘’ + “, refBean=” + refBean + ‘} ’; } }

  Spring框架就是通過(guò)這種方式將成員變量值以及依賴對(duì)象等都放在配置文件中進(jìn)行管理的,從而實(shí)現(xiàn)了較好地解耦(不過(guò)Spring是通過(guò)XML作為配置文件)。

  訪問(wèn)成員變量

  通過(guò)Class對(duì)象的的getField()方法可以獲取該類所包含的全部或指定的成員變量Field,F(xiàn)iled提供了如下兩組方法來(lái)讀取和設(shè)置成員變量值。

  - getXxx(Object obj): 獲取obj對(duì)象的該成員變量的值, 此處的Xxx對(duì)應(yīng)8中基本類型,如果該成員變量的類型是引用類型, 則取消get后面的Xxx;

  - setXxx(Object obj, Xxx val): 將obj對(duì)象的該成員變量值設(shè)置成val值。此處的Xxx對(duì)應(yīng)8種基本類型, 如果該成員類型是引用類型, 則取消set后面的Xxx;

  注: getDeclaredXxx方法可以獲取所有的成員變量,無(wú)論private/public;

  /** *@authorjifang *@since16/1/2下午1:00. */publicclassClient{@Testpublicvoidclient()throwsNoSuchFieldException, IllegalAccessException { User user = newUser(); Field idFiled = User.class.getDeclaredField( “id”); setAccessible(idFiled); idFiled.setInt(user,46); Field nameFiled = User.class.getDeclaredField( “name”); setAccessible(nameFiled); nameFiled.set(user, “feiqing”); Field passwordField = User.class.getDeclaredField(“password”); setAccessible(passwordField); passwordField.set(user,“ICy5YqxZB1uWSwcVLSNLcA==”); System.out.println(user); }privatevoidsetAccessible(AccessibleObject object) { object.setAccessible( true); } }使用反射獲取泛型信息

  為了通過(guò)反射操作泛型以迎合實(shí)際開(kāi)發(fā)的需要, Java新增了java.lang.reflect.ParameterizedType java.lang.reflect.GenericArrayTypejava.lang.reflect.TypeVariable java.lang.reflect.WildcardType幾種類型來(lái)代表不能歸一到Class類型但是又和原始類型同樣重要的類型。

  實(shí)例分析講解java中的反射機(jī)制

  其中, 我們可以使用ParameterizedType來(lái)獲取泛型信息。

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassClient{privateMap《String, Object》 objectMap; publicvoidtest(Map《String, User》 map, String string) { } publicMap《User, Bean》 test() { returnnull; } /** * 測(cè)試屬性類型 * *@throwsNoSuchFieldException */@TestpublicvoidtestFieldType()throwsNoSuchFieldException { Field field = Client.class.getDeclaredField( “objectMap”); Type gType = field.getGenericType(); // 打印type與generic type的區(qū)別System.out.println(field.getType()); System.out.println(gType); System.out.println(“**************”); if(gType instanceofParameterizedType) { ParameterizedType pType = (ParameterizedType) gType; Type[] types = pType.getActualTypeArguments(); for(Type type : types) { System.out.println(type.toString()); } } } /** * 測(cè)試參數(shù)類型 * *@throwsNoSuchMethodException */@TestpublicvoidtestParamType()throwsNoSuchMethodException { Method testMethod = Client.class.getMethod( “test”, Map.class, String.class); Type[] parameterTypes = testMethod.getGenericParameterTypes(); for(Type type : parameterTypes) { System.out.println( “type -》 ”+ type); if(type instanceofParameterizedType) { Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments(); for(Type actualType : actualTypes) { System.out.println( “/tactual type -》 ”+ actualType); } } } } /** * 測(cè)試返回值類型 * *@throwsNoSuchMethodException */@TestpublicvoidtestReturnType()throwsNoSuchMethodException { Method testMethod = Client.class.getMethod( “test”); Type returnType = testMethod.getGenericReturnType(); System.out.println( “return type -》 ”+ returnType); if(returnType instanceofParameterizedType) { Type[] actualTypes = ((ParameterizedType) returnType).getActualTypeArguments(); for(Type actualType : actualTypes) { System.out.println( “/tactual type -》 ”+ actualType); } } } }反射性能測(cè)試

  Method/Constructor/Field/Element都繼承了AccessibleObject,AccessibleObject類中有一個(gè)setAccessible方法:

  public void setAccessible(boolean flag) throws SecurityException { 。。.}

  該方法有兩個(gè)作用:

  啟用/禁用訪問(wèn)安全檢查開(kāi)關(guān):值為true,則指示反射的對(duì)象在使用時(shí)取消Java語(yǔ)言訪問(wèn)檢查;值為false,則指示應(yīng)該實(shí)施Java語(yǔ)言的訪問(wèn)檢查;

  可以禁止安全檢查, 提高反射的運(yùn)行效率。

  /** *@authorjifang *@since15/12/31下午4:53. */ public classTestReflect{ @Before publicvoid testNoneReflect() { User user = newUser(); longstart = System.currentTimeMillis();for( longi = 0; i 《 Integer.MAX_VALUE; ++i) { user.getName(); } longcount = System.currentTimeMillis() - start; System.out.println( “沒(méi)有反射, 共消耗 《”+ count + “》 毫秒”); } @Test public void testNotAccess() throwsClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { User user = newUser(); Method method = Class.forName(“com.fq.domain.User”).getMethod( “getName”); longstart = System.currentTimeMillis();for( longi = 0; i 《 Integer.MAX_VALUE; ++i) { method.invoke(user, null); } longcount = System.currentTimeMillis() - start; System.out.println( “沒(méi)有訪問(wèn)權(quán)限, 共消耗 《”+ count +“》 毫秒”); } @After public void testUseAccess() throwsClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { User user = newUser(); Method method = Class.forName(“com.fq.domain.User”).getMethod( “getName”); method.setAccessible( true); longstart = System.currentTimeMillis(); for( longi = 0; i 《 Integer.MAX_VALUE; ++i) { method.invoke(user, null); } longcount = System.currentTimeMillis() - start; System.out.println( “有訪問(wèn)權(quán)限, 共消耗 《”+ count + “》 毫秒”); } }

  執(zhí)行上面程序,在我的機(jī)器上會(huì)有如下結(jié)果:

  機(jī)器配置信息如下:

  實(shí)例分析講解java中的反射機(jī)制

  可以看到使用反射會(huì)比直接調(diào)用慢3000毫秒,但是前提是該方法會(huì)執(zhí)行20E+次(而且服務(wù)器的性能也肯定比我的機(jī)器要高),因此在我們的實(shí)際開(kāi)發(fā)中,其實(shí)是不用擔(dān)心反射機(jī)制帶來(lái)的性能消耗的,而且禁用訪問(wèn)權(quán)限檢查,也會(huì)有性能的提升。

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?
      主站蜘蛛池模板: 你懂的免费在线 | 国产看午夜精品理论片 | 欧美一卡二卡3卡4卡无卡六卡七卡科普 | 夜夜艹天天干 | 精品午夜视频 | 在线看黄网 | 日操夜操| 亚洲视频欧美视频 | 老外一级黄色片 | a成人| 痴女中文字幕在线视频 | 天天狠狠操 | 日本免费观看网站 | aa亚洲| 日本色图在线 | 午夜va | 狠狠狠色丁香婷婷综合激情 | h视频在线观看视频观看 | 日韩一级在线观看 | 久久综合九色综合98一99久久99久 | 91久久婷婷国产综合精品青草 | 年轻人影院www你懂的 | 欧美aaaaa性bbbbb小妇 | 日日久 | 777色狠狠一区二区三区香蕉 | 精品久久天干天天天按摩 | 九色愉拍自拍 | 亚州色吧 | 香蕉视频网站在线播放 | 奇米777me| 欧美国产一区二区二区 | 在线视频综合网 | 日本色图视频 | 国产三片理论电影在线 | 白嫩美女一级高清毛片免费看 | 日本综合视频 | 色中涩| 日本一本在线视频 | 在线播放真实国产乱子伦 | 黄色短视频免费看 | 色综合天天干 |