中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

Java 反射(she)機(ji)制淺析

      Java反射機制是在運行狀態中,對于任意一個,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能(neng)夠調(diao)用(yong)它(ta)(ta)的(de)(de)任意一個方(fang)法和屬性;這(zhe)種動態獲取的(de)(de)信息以(yi)及動態調(diao)用(yong)對(dui)象的(de)(de)方(fang)法的(de)(de)功能(neng)稱為Java語言的(de)(de)反射(she)機(ji)(ji)制。反射(she)的(de)(de)概(gai)念(nian)是(shi)由Smith在1982年首次提出的(de)(de),主要是(shi)指程(cheng)序可(ke)以(yi)訪問、檢測和修改它(ta)(ta)本身狀態或(huo)行(xing)為的(de)(de)一種能(neng)力。這(zhe)一概(gai)念(nian)的(de)(de)提出很(hen)快(kuai)引發(fa)了計(ji)(ji)算機(ji)(ji)科(ke)學(xue)領域(yu)關于應用(yong)反射(she)性的(de)(de)研究。它(ta)(ta)首先被程(cheng)序語言的(de)(de)設計(ji)(ji)領域(yu)所采(cai)用(yong),并(bing)在Lisp和面向對(dui)象方(fang)面取得了成績(ji)。當然反射(she)本身并(bing)不是(shi)一個新概(gai)念(nian),它(ta)(ta)可(ke)能(neng)會使(shi)我們聯想到光學(xue)中(zhong)的(de)(de)反射(she)概(gai)念(nian),盡管計(ji)(ji)算機(ji)(ji)科(ke)學(xue)賦予了反射(she)概(gai)念(nian)新的(de)(de)含義,但是(shi),從(cong)現象上來(lai)說,它(ta)(ta)們確實有某些相通之處,這(zhe)些有助(zhu)于我們的(de)(de)理(li)解。

      Java反(fan)射機制主(zhu)要提供下面幾種用途:

  • 在運行時判斷任意一個對象所屬的類
  • 在運行時構造任意一個類的對象
  • 在運行時判斷任意一個類所具有的成員變量和方法
  • 在運行時調用任意一個對象的方法

      首先看一個簡單(dan)的(de)例(li)子,通過這個例(li)子來理解(jie)Java的(de)反(fan)射機(ji)制是如何(he)工作(zuo)的(de)。

View Code
package com.wanggc.reflection;

import java.lang.reflect.Method;

/**
* Java 反射練習。
*
*
@author Wanggc
*/
public class ForNameTest {

/**
* 入口函數。
*
*
@param args
* 參數
*
@throws Exception
* 錯誤信息
*/
public static void main(String[] args) throws Exception {
// 獲得Class
Class<?> cls = Class.forName(args[0]);
// 通過(guo)Class獲得所對應對象的方法
Method[] methods = cls.getMethods();
// 輸出每(mei)個方法名
for (Method method : methods) {
System.out.println(method);
}
}
}

    &nbsp; 當傳(chuan)入(ru)的(de)參數是java.lang.String時,會輸出(chu)如下結果

View Code
public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public int java.lang.String.hashCode()
public int java.lang.String.compareTo(java.lang.String)
public int java.lang.String.compareTo(java.lang.Object)
public int java.lang.String.indexOf(int)
public int java.lang.String.indexOf(int,int)
public int java.lang.String.indexOf(java.lang.String)
public int java.lang.String.indexOf(java.lang.String,int)
public static java.lang.String java.lang.String.valueOf(int)
public static java.lang.String java.lang.String.valueOf(char)
public static java.lang.String java.lang.String.valueOf(boolean)
public static java.lang.String java.lang.String.valueOf(float)
public static java.lang.String java.lang.String.valueOf(char[],int,int)
public static java.lang.String java.lang.String.valueOf(double)
public static java.lang.String java.lang.String.valueOf(char[])
public static java.lang.String java.lang.String.valueOf(java.lang.Object)
public static java.lang.String java.lang.String.valueOf(long)
public char java.lang.String.charAt(int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int)
public int java.lang.String.compareToIgnoreCase(java.lang.String)
public java.lang.String java.lang.String.concat(java.lang.String)
public boolean java.lang.String.contains(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.StringBuffer)
public static java.lang.String java.lang.String.copyValueOf(char[])
public static java.lang.String java.lang.String.copyValueOf(char[],int,int)
public boolean java.lang.String.endsWith(java.lang.String)
public boolean java.lang.String.equalsIgnoreCase(java.lang.String)
public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[])
public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[])
public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException
public void java.lang.String.getBytes(int,int,byte[],int)
public byte[] java.lang.String.getBytes()
public byte[] java.lang.String.getBytes(java.nio.charset.Charset)
public void java.lang.String.getChars(int,int,char[],int)
public native java.lang.String java.lang.String.intern()
public boolean java.lang.String.isEmpty()
public int java.lang.String.lastIndexOf(java.lang.String)
public int java.lang.String.lastIndexOf(int,int)
public int java.lang.String.lastIndexOf(int)
public int java.lang.String.lastIndexOf(java.lang.String,int)
public int java.lang.String.length()
public boolean java.lang.String.matches(java.lang.String)
public int java.lang.String.offsetByCodePoints(int,int)
public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int)
public boolean java.lang.String.regionMatches(int,java.lang.String,int,int)
public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence)
public java.lang.String java.lang.String.replace(char,char)
public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String)
public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String,int)
public boolean java.lang.String.startsWith(java.lang.String)
public boolean java.lang.String.startsWith(java.lang.String,int)
public java.lang.CharSequence java.lang.String.subSequence(int,int)
public java.lang.String java.lang.String.substring(int)
public java.lang.String java.lang.String.substring(int,int)
public char[] java.lang.String.toCharArray()
public java.lang.String java.lang.String.toLowerCase()
public java.lang.String java.lang.String.toLowerCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase()
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.trim()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

      這樣就列(lie)出(chu)了java.lang.String類(lei)的所有方(fang)(fang)(fang)(fang)法(fa)名、及其限制符、返(fan)回(hui)類(lei)型及拋出(chu)的異常。這個(ge)程序使用(yong)Class類(lei)forName方(fang)(fang)(fang)(fang)法(fa)載入指定的類(lei),然后調用(yong)getMethods方(fang)(fang)(fang)(fang)法(fa)返(fan)回(hui)指定類(lei)的方(fang)(fang)(fang)(fang)法(fa)列(lie)表(biao)。java.lang.reflect.Method用(yong)來表(biao)述某個(ge)類(lei)中的單一方(fang)(fang)(fang)(fang)法(fa)。

      使(shi)用java的反射機制,一般需要遵循三(san)步:

    1. 獲得你想操作類的Class對象
    2. 通過第一步獲得的Class對象去取得操作類的方法或是屬性名
    3. 操作第二步取得的方法或是屬性

     Java運行(xing)的(de)(de)(de)時候,某個類無論(lun)生成(cheng)多少個對象,他(ta)們都會對應同一個Class對象,它表示正在運行(xing)程序中的(de)(de)(de)類和(he)接口。如何取得操作類的(de)(de)(de)Class對象,常用的(de)(de)(de)有三(san)種方(fang)式:

    1. 調用Class的靜態方法forName,如上例;
    2. 使用類的.class語法,如:Class<?> cls = String.class;
    3. 調用對象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();

   &nbsp;  下面(mian)將通過實例講述如何(he)通過前(qian)面(mian)所訴的三步來執行某對象的某個方法(fa):

View Code
 1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Method;
4
5 /**
6 * Java 反射練習。
7 *
8 * @author Wanggc
9 */
10 public class ReflectionTest {
11 public static void main(String[] args) throws Exception {
12 DisPlay disPlay = new DisPlay();
13 // 獲(huo)得Class
14 Class<?> cls = disPlay.getClass();
15 // 通(tong)過Class獲得DisPlay類(lei)的show方法
16 Method method = cls.getMethod("show", String.class);
17 // 調用show方(fang)法(fa)
18 method.invoke(disPlay, "Wanggc");
19 }
20 }
21
22 class DisPlay {
23 public void show(String name) {
24 System.out.println("Hello :" + name);
25 }
26 }

      前面說(shuo)過,Java程序(xu)的(de)(de)(de)每個(ge)(ge)(ge)類(lei)(lei)都會有個(ge)(ge)(ge)Class對(dui)象(xiang)(xiang)與之對(dui)應(ying)。Java反(fan)射(she)的(de)(de)(de)第(di)一步就是(shi)(shi)獲得這個(ge)(ge)(ge)Class對(dui)象(xiang)(xiang),如代(dai)碼(ma)14行(xing)(xing)(xing)(xing)。當然(ran)(ran),每個(ge)(ge)(ge)類(lei)(lei)的(de)(de)(de)方(fang)法(fa)(fa)(fa)(fa)也(ye)必有一個(ge)(ge)(ge)Method對(dui)象(xiang)(xiang)與之對(dui)應(ying)。要通過反(fan)射(she)的(de)(de)(de)方(fang)式調用這個(ge)(ge)(ge)方(fang)法(fa)(fa)(fa)(fa),就要首先獲得這個(ge)(ge)(ge)方(fang)法(fa)(fa)(fa)(fa)的(de)(de)(de)Method對(dui)象(xiang)(xiang),如代(dai)碼(ma)16行(xing)(xing)(xing)(xing),然(ran)(ran)后用Method對(dui)象(xiang)(xiang)反(fan)過來調用這個(ge)(ge)(ge)方(fang)法(fa)(fa)(fa)(fa),如代(dai)碼(ma)18行(xing)(xing)(xing)(xing)。注(zhu)意(yi)(yi)16行(xing)(xing)(xing)(xing)getMethod方(fang)法(fa)(fa)(fa)(fa)的(de)(de)(de)第(di)一個(ge)(ge)(ge)參數(shu)是(shi)(shi)方(fang)法(fa)(fa)(fa)(fa)名(ming),第(di)二個(ge)(ge)(ge)是(shi)(shi)此方(fang)法(fa)(fa)(fa)(fa)的(de)(de)(de)參數(shu)類(lei)(lei)型(xing),如果(guo)是(shi)(shi)多個(ge)(ge)(ge)參數(shu),接著添加參數(shu)就可以了,因為(wei)getMethod是(shi)(shi)可變(bian)參數(shu)方(fang)法(fa)(fa)(fa)(fa)。執(zhi)行(xing)(xing)(xing)(xing)18行(xing)(xing)(xing)(xing)代(dai)碼(ma)的(de)(de)(de)invoke方(fang)法(fa)(fa)(fa)(fa),其實也(ye)就是(shi)(shi)執(zhi)行(xing)(xing)(xing)(xing)show方(fang)法(fa)(fa)(fa)(fa),注(zhu)意(yi)(yi)invoke的(de)(de)(de)第(di)一個(ge)(ge)(ge)參數(shu),是(shi)(shi)DisPlay類(lei)(lei)的(de)(de)(de)一個(ge)(ge)(ge)對(dui)象(xiang)(xiang),也(ye)就是(shi)(shi)調用DisPlay類(lei)(lei)哪個(ge)(ge)(ge)對(dui)象(xiang)(xiang)的(de)(de)(de)show方(fang)法(fa)(fa)(fa)(fa),第(di)二個(ge)(ge)(ge)參數(shu)是(shi)(shi)給show方(fang)法(fa)(fa)(fa)(fa)傳遞的(de)(de)(de)參數(shu)。類(lei)(lei)型(xing)和個(ge)(ge)(ge)數(shu)一定要與16行(xing)(xing)(xing)(xing)的(de)(de)(de)getMethod方(fang)法(fa)(fa)(fa)(fa)一直。

  &nbsp;   上例講述了(le)如(ru)何(he)通過反(fan)射調用某(mou)(mou)個類(lei)的方(fang)法,下面(mian)將再通過一個實例講述如(ru)何(he)通過反(fan)射給某(mou)(mou)個類(lei)的屬性賦值:

View Code
  1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Field;
4
5 /**
6 * Java 反射之屬性練習。
7 *
8 * @author Wanggc
9 */
10 public class ReflectionTest {
11 public static void main(String[] args) throws Exception {
12 // 建(jian)立學生對(dui)象
13 Student student = new Student();
14 // 為(wei)學生對象賦值
15 student.setStuName("Wanggc");
16 student.setStuAge(24);
17 // 建立(li)拷貝目標對象
18 Student destStudent = new Student();
19 // 拷貝(bei)學生對象
20 copyBean(student, destStudent);
21 // 輸出拷貝結果
22 System.out.println(destStudent.getStuName() + ":"
23 + destStudent.getStuAge());
24 }
25
26 /**
27 * 拷貝學生對象信息。
28 *
29 * @param from
30 * 拷貝源對象
31 * @param dest
32 * 拷貝目標對象
33 * @throws Exception
34 * 例外
35 */
36 private static void copyBean(Object from, Object dest) throws Exception {
37 // 取得(de)拷(kao)貝(bei)源對象(xiang)的(de)Class對象(xiang)
38 Class<?> fromClass = from.getClass();
39 // 取得拷貝源對(dui)象(xiang)的屬性(xing)列表(biao)
40 Field[] fromFields = fromClass.getDeclaredFields();
41 // 取得拷(kao)貝目標對象的Class對象
42 Class<?> destClass = dest.getClass();
43 Field destField = null;
44 for (Field fromField : fromFields) {
45 // 取(qu)得拷貝源對象的屬性名字
46 String name = fromField.getName();
47 // 取得(de)拷貝目標(biao)對象的相同名稱的屬性
48 destField = destClass.getDeclaredField(name);
49 // 設置屬(shu)性的可(ke)訪問(wen)性
50 fromField.setAccessible(true);
51 destField.setAccessible(true);
52 // 將拷貝源(yuan)對(dui)象(xiang)的屬性的值(zhi)賦給拷貝目標對(dui)象(xiang)相應(ying)的屬性
53 destField.set(dest, fromField.get(from));
54 }
55 }
56 }
57
58 /**
59 * 學生類。
60 */
61 class Student {
62 /** 姓(xing)名 */
63 private String stuName;
64 /** 年(nian)齡(ling) */
65 private int stuAge;
66
67 /**
68 * 獲取學生姓名。
69 *
70 * @return 學生姓名
71 */
72 public String getStuName() {
73 return stuName;
74 }
75
76 /**
77 * 設置學生姓名
78 *
79 * @param stuName
80 * 學生姓名
81 */
82 public void setStuName(String stuName) {
83 this.stuName = stuName;
84 }
85
86 /**
87 * 獲取學生年齡
88 *
89 * @return 學生年齡
90 */
91 public int getStuAge() {
92 return stuAge;
93 }
94
95 /**
96 * 設置學生年齡
97 *
98 * @param stuAge
99 * 學生年齡
100 */
101 public void setStuAge(int stuAge) {
102 this.stuAge = stuAge;
103 }
104 }

       Java的發(fa)射機制中類有Class對(dui)應,類的方(fang)(fang)法(fa)有Method對(dui)應,當(dang)然屬(shu)(shu)性也(ye)有Field與之(zhi)對(dui)應。代碼(ma)中注釋已(yi)經做了(le)詳(xiang)細(xi)的注釋,在(zai)此不再贅述。但(dan)要注意,Field提供了(le)get和set方(fang)(fang)法(fa)獲取和設(she)置屬(shu)(shu)性的值,但(dan)是由于屬(shu)(shu)性是私有類型,所(suo)以(yi)(yi)需要設(she)置屬(shu)(shu)性的可(ke)訪(fang)(fang)問性為true,如(ru)代碼(ma)50~51行。也(ye)可(ke)以(yi)(yi)在(zai)為整個(ge)fields設(she)置可(ke)訪(fang)(fang)問性,在(zai)40行下面使(shi)用AccessibleObject的靜態方(fang)(fang)法(fa)setAccessible,如(ru):AccessibleObject.setAccessible(fromFields, true);

   &nbsp;  前面講(jiang)述了(le)如何用Java反射(she)機(ji)制操作(zuo)一(yi)個類的方法(fa)和屬(shu)性(xing),下面再通過一(yi)個實例講(jiang)述如何在運行時創建類的一(yi)個對象(xiang):

View Code
 1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Field;
4
5 /**
6 * Java 反射之屬性練習。
7 *
8 * @author Wanggc
9 */
10 public class ReflectionTest {
11 public static void main(String[] args) throws Exception {
12 // 建立學生對象
13 Student student = new Student();
14 // 為學(xue)生對象賦(fu)值
15 student.setStuName("Wanggc");
16 student.setStuAge(24);
17 // 建立拷貝目標對象(xiang)
18 Student destStudent = (Student) copyBean(student);
19 // 輸出拷貝結果
20 System.out.println(destStudent.getStuName() + ":"
21 + destStudent.getStuAge());
22 }
23
24 /**
25 * 拷貝學生對象信息。
26 *
27 * @param from
28 * 拷貝源對象
29 * @param dest
30 * 拷貝目標對象
31 * @throws Exception
32 * 例外
33 */
34 private static Object copyBean(Object from) throws Exception {
35 // 取(qu)得拷(kao)貝源對象(xiang)(xiang)的Class對象(xiang)(xiang)
36 Class<?> fromClass = from.getClass();
37 // 取(qu)得(de)拷貝源對(dui)象的屬性(xing)列表(biao)
38 Field[] fromFields = fromClass.getDeclaredFields();
39 // 取(qu)得(de)拷貝目標對象的(de)Class對象
40 Object ints = fromClass.newInstance();
41 for (Field fromField : fromFields) {
42 // 設置屬性的(de)可訪(fang)問性
43 fromField.setAccessible(true);
44 // 將(jiang)拷(kao)貝(bei)源對象的(de)(de)屬性的(de)(de)值賦(fu)給拷(kao)貝(bei)目標對象相應的(de)(de)屬性
45 fromField.set(ints, fromField.get(from));
46 }
47
48 return ints;
49 }
50 }
51
52 /**
53 * 學生類。
54 */
55 class Student {
56 /** 姓名 */
57 private String stuName;
58 /** 年齡 */
59 private int stuAge;
60
61 /**
62 * 獲取學生姓名。
63 *
64 * @return 學生姓名
65 */
66 public String getStuName() {
67 return stuName;
68 }
69
70 /**
71 * 設置學生姓名
72 *
73 * @param stuName
74 * 學生姓名
75 */
76 public void setStuName(String stuName) {
77 this.stuName = stuName;
78 }
79
80 /**
81 * 獲取學生年齡
82 *
83 * @return 學生年齡
84 */
85 public int getStuAge() {
86 return stuAge;
87 }
88
89 /**
90 * 設置學生年齡
91 *
92 * @param stuAge
93 * 學生年齡
94 */
95 public void setStuAge(int stuAge) {
96 this.stuAge = stuAge;
97 }
98 }

      此(ci)例(li)和(he)上例(li)運行的(de)(de)結果是相同(tong)的(de)(de)。但是copyBean方法返回的(de)(de)對象不再是外面傳(chuan)入(ru)的(de)(de),而是由方法內部(bu)產生的(de)(de),如第(di)40行代碼(ma)所示。注(zhu)意:Class的(de)(de)newInstance方法,只能創(chuang)建只包含(han)無參數(shu)的(de)(de)構(gou)造函(han)數(shu)的(de)(de)類,如果某(mou)類只有帶(dai)參數(shu)的(de)(de)構(gou)造函(han)數(shu),那么就要使用(yong)另外一種方式:fromClass.getDeclaredConstructor(int.class,String.class).newInstance(24,"wanggc");

    ;  至此,Java反射機(ji)制(zhi)的(de)常用(yong)(yong)機(ji)能(運行時調用(yong)(yong)對象的(de)方法、類(lei)屬性的(de)使(shi)用(yong)(yong)、創類(lei)類(lei)的(de)對象)已經介紹完(wan)了。

      補充(chong):在獲(huo)得類(lei)的(de)方法(fa)、屬性(xing)(xing)、構造函數時,會有getXXX和(he)getgetDeclaredXXX兩種對(dui)應的(de)方法(fa)。之間的(de)區別在于(yu)前者返(fan)回(hui)的(de)是訪問(wen)權限(xian)為public的(de)方法(fa)和(he)屬性(xing)(xing),包括(kuo)父(fu)類(lei)中(zhong)的(de);但后者返(fan)回(hui)的(de)是所有訪問(wen)權限(xian)的(de)方法(fa)和(he)屬性(xing)(xing),不(bu)包括(kuo)父(fu)類(lei)的(de)。

     


 

 

posted @ 2012-01-27 00:53  孤旅者  閱讀(28690)  評論(10)    收藏  舉報