一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

java反射實(shí)例解析

大?。?/span>0.7 MB 人氣: 2017-09-27 需要積分:1

  Class類的構(gòu)造方法是private,由JVM創(chuàng)建。

  反射是java語言的一個(gè)特性,它允程序在運(yùn)行時(shí)(注意不是編譯的時(shí)候)來進(jìn)行自我檢查并且對(duì)內(nèi)部的成員進(jìn)行操作。例如它允許一個(gè)java的類獲取他所有的成員變量和方法并且顯示出來。Java 的這一能力在實(shí)際應(yīng)用中也許用得不是很多,但是在其它的程序設(shè)計(jì)語言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數(shù)定義相關(guān)的信息。 (來自Sun)

  JavaBean 是 reflection 的實(shí)際應(yīng)用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過 reflection 動(dòng)態(tài)的載入并取得 Java 組件(類) 的屬性。

  反射是從1.2就有的,后面的三大框架都會(huì)用到反射機(jī)制,涉及到類”Class”,無法直接new CLass(),其對(duì)象是內(nèi)存里的一份字節(jié)碼。

  Class 類的實(shí)例表示正在運(yùn)行的 Java 應(yīng)用程序中的類和接口。枚舉是一種類,注釋是一種接口。每個(gè)數(shù)組屬于被映射為 Class 對(duì)象的一個(gè)類,所有具有相同元素類型和維數(shù)的數(shù)組都共享該 Class 對(duì)象?;镜?Java類型(boolean、byte、char、short、int、long、float 和 double)和關(guān)鍵字 void 也表示為 Class 對(duì)象。Class 沒有公共構(gòu)造方法。Class 對(duì)象是在加載類時(shí)由 Java 虛擬機(jī)以及通過調(diào)用類加載器中的 defineClass 方法自動(dòng)構(gòu)造的。

  1Person p1 = newPerson(); 2//下面的這三種方式都可以得到字節(jié)碼3CLass c1 =Date.class(); 4p1.getClass(); 5//若存在則加載,否則新建,往往使用第三種,類的名字在寫源程序時(shí)不需要知道,到運(yùn)行時(shí)再傳遞過來6Class.forName( “java.lang.String”);

  CLass.forName()字節(jié)碼已經(jīng)加載到j(luò)ava虛擬機(jī)中,去得到字節(jié)碼;java虛擬機(jī)中還沒有生成字節(jié)碼 用類加載器進(jìn)行加載,加載的字節(jié)碼緩沖到虛擬機(jī)中。

  考慮下面這個(gè)簡(jiǎn)單的例子,讓我們看看 reflection 是如何工作的。

  import java.lang.reflect.*; publicclassDumpMethods { publicstaticvoidmain(String args[]) {try{ Class c = Class.forName( “java.util.Stack”); Method m[] = c.getDeclaredMethods();for( inti = 0; i 《 m.length; i++) System. out.println(m[i].toString()); } catch(Throwable e){ System.err.println(e); } } } 1public synchronized java .lang.Objectjava .util.Stack.pop()2public java .lang.Objectjava .util.Stack.push(java .lang.Object) 3public boolean java.util.Stack.empty() 4public synchronized java .lang.Objectjava .util.Stack.peek() 5public synchronized int java .util.Stack.search(java .lang.Object)

  這樣就列出了java.util.Stack 類的各方法名以及它們的限制符和返回類型。這個(gè)程序使用 Class.forName 載入指定的類,然后調(diào)用 getDeclaredMethods 來獲取這個(gè)類中定義了的方法列表。java.lang.reflect.Methods 是用來描述某個(gè)類中單個(gè)方法的一個(gè)類。

  以下示例使用 Class 對(duì)象來顯示對(duì)象的類名:

  1void printClassName(Object obj) { 2System .out.println( “The class of ”+ obj + 3“ is ”+ obj.getClass() .getName()) ;4}

  還可以使用一個(gè)類字面值(JLS Section 15.8.2)來獲取指定類型(或 void)的 Class 對(duì)象。例如:

  1System .out.println( “The name of class Foo is: ”+Foo .class.getName()) ;

  在沒有對(duì)象實(shí)例的時(shí)候,主要有兩種辦法。

  //獲得類類型的兩種方式 Class cls1 = Role. class; Class cls2 = Class.forName( “yui.Role”);

  注意第二種方式中,forName中的參數(shù)一定是完整的類名(包名+類名),并且這個(gè)方法需要捕獲異常?,F(xiàn)在得到cls1就可以創(chuàng)建一個(gè)Role類的實(shí)例了,利用Class的newInstance方法相當(dāng)于調(diào)用類的默認(rèn)的構(gòu)造器。

  1Objecto = cls1.newInstance(); 2//創(chuàng)建一個(gè)實(shí)例 3//Object o1 = new Role(); //與上面的方法等價(jià)二。常用方法

  1.isPrimitive(判斷是否是基本類型的字節(jié)碼)

  publicclassTestReflect { publicstaticvoidmain(String[] args) { // TODO Auto-generated method stubString str = “abc”; Class cls1 = str.getClass(); Class cls2 = String. class; Class cls3 = null; //必須要加上nulltry{ cls3 = Class.forName( “java.lang.String”); }catch(ClassNotFoundException e) { // TODO Auto-generated catch blocke.printStackTrace(); } System. out.println(cls1==cls2); System.out.println(cls1==cls3); System. out.println(cls1.isPrimitive()); System. out.println( int.class.isPrimitive()); //判定指定的 Class 對(duì)象是否表示一個(gè)基本類型。System. out.println(int. class== Integer. class); System. out.println( int. class== Integer.TYPE); System.out.println( int[]。 class.isPrimitive()); System. out.println( int[]。 class.isArray()); } } /* * true true false true false true false true */*/

  2.getConstructor和getConstructors()

  java中構(gòu)造方法沒有先后順序,通過類型和參數(shù)個(gè)數(shù)區(qū)分。

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassTestReflect{publicstaticvoidmain(String[] args) throwsSecurityException, NoSuchMethodException { // TODO Auto-generated method stubString str = “abc”; System.out.println(String.class.getConstructor(StringBuffer.class)); } }

  3.Filed類代表某一類中的一個(gè)成員變量。

  import java.lang.reflect.Field; publicclassTestReflect { publicstaticvoidmain(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception { ReflectPointer rp1 = newReflectPointer( 3, 4); Field fieldx = rp1.getClass().getField( “x”); //必須是x或者ySystem. out.println(fieldx. get(rp1)); /* * private的成員變量必須使用getDeclaredField,并setAccessible(true),否則看得到拿不到 */Field fieldy = rp1.getClass().getDeclaredField( “y”); fieldy.setAccessible( true); //暴力反射System. out.println(fieldy. get(rp1)); } } class ReflectPointer { publicintx = 0; privateinty =0; publicReflectPointer( intx, inty) { //alt + shift +s相當(dāng)于右鍵sourcesuper(); // TODO Auto-generated constructor stubthis.x = x; this.y = y; } }三。典型例題

  1.將所有String類型的成員變量里的b改成a。

  importjava.lang.reflect.Field; publicclassTestReflect{publicstaticvoidmain(String[] args)throwsSecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception { ReflectPointer rp1 = newReflectPointer( 3, 4); changeBtoA(rp1); System.out.println(rp1); } privatestaticvoidchangeBtoA(Object obj)throwsRuntimeException, Exception { Field[] fields = obj.getClass().getFields(); for(Field field : fields) { //if(field.getType().equals(String.class))//由于字節(jié)碼只有一份,用equals語義不準(zhǔn)確if(field.getType()==String.class) { String oldValue = (String)field.get(obj); String newValue = oldValue.replace( ‘b’, ‘a(chǎn)’); field.set(obj,newValue); } } } } class ReflectPointer {privateintx = 0; publicinty = 0; publicString str1 = “ball”; publicString str2 = “basketball”;publicString str3 = “itcat”; publicReflectPointer( intx, inty) { //alt + shift +s相當(dāng)于右鍵sourcesuper(); // TODO Auto-generated constructor stubthis.x = x; this.y = y; }@OverridepublicString toString() { return“ReflectPointer [str1=”+ str1 + “, str2=”+ str2 + “, str3=”+ str3 + “]”; } }

  2.寫一個(gè)程序根據(jù)用戶提供的類名,調(diào)用該類的里的main方法。

  為什么要用反射的方式呢?

  importjava.lang.reflect.Field; importjava.lang.reflect.Method; /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassTestReflect{publicstaticvoidmain(String[] args)throwsSecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception { String str = args[ 0]; /* * 這樣會(huì)數(shù)組角標(biāo)越界,因?yàn)閴焊鶝]有這個(gè)字符數(shù)組 * 需要右鍵在run as-configurations-arguments里輸入b.Inter(完整類名) * */Method m = Class.forName(str).getMethod( “main”,String[].class); //下面這兩種方式都可以,main方法需要一個(gè)參數(shù)m.invoke( null, newObject[]{ newString[]{ “111”, “222”,“333”}}); m.invoke( null, (Object) newString[]{ “111”, “222”, “333”}); //這個(gè)可以說明,數(shù)組也是Object/* * m.invoke(null, new String[]{“111”,“222”,“333”}) * 上面的不可以,因?yàn)閖ava會(huì)自動(dòng)拆包 */} } class Inter { publicstaticvoidmain(String[] args) { for(Object obj : args) { System.out.println(obj); } } }

  3.模擬 instanceof 操作符

  class S { } publicclassIsInstance { publicstaticvoidmain(String args[]) { try{ Class cls = Class.forName( “S”); boolean b1 = cls.isInstance( newInteger( 37)); System.out.println(b1); boolean b2 = cls.isInstance( newS()); System. out.println(b2); }catch(Throwable e) { System.err.println(e); } } }

  在這個(gè)例子中創(chuàng)建了一個(gè)S 類的 Class 對(duì)象,然后檢查一些對(duì)象是否是S的實(shí)例。Integer(37) 不是,但 new S()是。

  四.Method類

  代表類(不是對(duì)象)中的某一方法。

  import java.lang.reflect.Field; import java.lang.reflect.Method; /* * 人在黑板上畫圓,涉及三個(gè)對(duì)象,畫圓需要圓心和半徑,但是是私有的,畫圓的方法 * 分配給人不合適。Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! * * 司機(jī)踩剎車,司機(jī)只是給列車發(fā)出指令,剎車的動(dòng)作還需要列車去完成。 * * 面試經(jīng)??济嫦?qū)ο蟮脑O(shè)計(jì),比如人關(guān)門,人只是去推門。 * * 這就是專家模式:誰擁有數(shù)據(jù),誰就是專家,方法就分配給誰 */publicclassTestReflect {publicstaticvoidmain(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception { String str = “shfsfs”; //包開頭是com表示是sun內(nèi)部用的,java打頭的才是用戶的Method mtCharAt = String.class.getMethod( “charAt”, int.class); Object ch = mtCharAt.invoke(str, 1); //若第一個(gè)參數(shù)是null,則肯定是靜態(tài)方法System. out.println(ch); System.out.println(mtCharAt.invoke(str, newObject[]{ 2})); //1.4語法} }五。數(shù)組的反射

  Array工具類用于完成數(shù)組的反射操作。

  同類型同緯度有相同的字節(jié)碼。

  int.class和Integer.class不是同一份字節(jié)碼,Integer.TYPE,TYPE代表包裝類對(duì)應(yīng)的基本類的字節(jié)碼 int.class==Integer.TYPE

  import java.util.Arrays; /* * 從這個(gè)例子看出即便字節(jié)碼相同但是對(duì)象也不一定相同,根本不是一回事 * */publicclassTestReflect { publicstaticvoidmain(String[] args) throws SecurityException, NoSuchMethodException, NoSuchFieldException, IllegalArgumentException, Exception { int[] a = newint[ 3]; int[] b = newint[]{ 4, 5, 5}; //直接賦值后不可以指定長(zhǎng)度,否則CEint[][] c = newint[ 3][ 2]; String[] d = newString[]{ “jjj”,“kkkk”}; System. out.println(a==b); //falseSystem. out.println(a.getClass()==b.getClass());//true//System.out.println(a.getClass()==d.getClass()); //比較字節(jié)碼a和cd也沒法比System.out.println(a.getClass()); //輸出class [ISystem. out.println(a.getClass().getName()); //輸出[I,中括號(hào)表示數(shù)組,I表示整數(shù)System. out.println(a.getClass().getSuperclass()); //輸出class java.lang.ObjectSystem. out.println(d.getClass().getSuperclass()); //輸出class java.lang.Object//由于父類都是Object,下面都是可以的Object obj1 = a; //不可是Object[]Object obj2 = b; Object[] obj3 = c; //基本類型的一位數(shù)組只可以當(dāng)做Object,非得還可以當(dāng)做Object[]Object obj4 = d; //注意asList處理int[]和String[]的區(qū)別System.out.println(Arrays.asList(b)); //1.4沒有可變參數(shù),使用的是數(shù)組,[[I@1bc4459]System.out.println(Arrays.asList(d)); //[jjj, kkkk]} }六。結(jié)束語 以上就是反射機(jī)制的簡(jiǎn)單的使用,顯然學(xué)過spring的朋友一定明白了,為什么可以通過配置文件就可以讓我們獲得指定的方法和變量,在我們創(chuàng)建對(duì)象的時(shí)候都是通過傳進(jìn)string實(shí)現(xiàn)的,就好像你需要什么,我們?nèi)槟闵a(chǎn),還有我們一直在用Object,這就說明java語言的動(dòng)態(tài)特性,依賴性大大的降低了。

非常好我支持^.^

(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ī)定!

      ?