java反射詳解

java反射詳解

JAVA反射機制:「 程序運行時,容許改變程序結構或 變量類型,這種語言稱爲 動態語言」。從這個觀點看,Perl,Python,Ruby是 動態語言,C++,Java,C#不是動態語言。可是JAVA有着一個很是突出的動態相關機制:Reflection,用在Java身上指的是咱們能夠於運行時加載、探知、使用編譯期間徹底未知的classes。換句話說,Java程序能夠加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。
 
JAVA反射機制定義
JAVA反射機制是在 運行狀態中,對於任意一個 ,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
 
Java反射機制主要提供瞭如下功能: 在運行時判斷任意一個對象所屬的類;在運行時構造任意一個類的對象;在運行時判斷任意一個類所具備的 成員變量和方法;在運行時調用任意一個對象的方法;生成動態代理。
 
有時候咱們說某個語言具備很強的動態性,有時候咱們會區分動態和靜態的不一樣技術與做法。咱們朗朗上口 動態綁定(dynamic binding)、 動態連接(dynamic linking)、動態加載(dynamic loading)等。然而「動態」一詞其實沒有絕對而廣泛適用的嚴格定義,有時候甚至像對象導向當初被導入編程領域同樣,一人一把號,各吹各的調。
通常而言,開發者社羣說到 動態語言,大體認同的一個定義是:「程序運行時,容許改變程序結構或 變量類型,這種語言稱爲動態語言」。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。
 
儘管在這樣的定義與分類下Java不是 動態語言,它卻有着一個很是突出的動態相關 機制:Reflection。這個字的意思是「反射、映象、倒影」,用在Java身上指的是咱們能夠於運行時加載、探知、使用編譯期間徹底未知的classes。換句話說,Java程序能夠加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。這種「看透class」的能力(the ability of the program to examine itself)被稱爲introspection(內省、內觀、檢討)。Reflection和introspection是常被並提的兩個術語。
 
Java如何可以作出上述的動態特性呢?這是一個深遠話題,本文對此只簡單介紹一些概念。整個篇幅最主要仍是介紹Reflection APIs,也就是讓讀者知道如何探索class的結構、如何對某個「運行時才獲知名稱的class」生成一份實體、爲其fields設值、調用其methods。本文將談到java.lang.Class,以及 java.lang.reflect中的Method、Field、Constructor等等classes。

 

給個例子,還原一個類:html

public void testReflect() throws ClassNotFoundException, SecurityException, NoSuchMethodException{
Class clazz = Class.forName("cn.reflect.FooInstance");//加載本身寫的類
System.out.println("----------------start constructors print-------------------");
Constructor[] constructors = clazz.getDeclaredConstructors();//獲取該類中申明的構造函數包括private函數, 但不包括父類的構造函數
for(Constructor cons:constructors){String param ="";for(Class str:cons.getParameterTypes()){param +=str+",";}  java

System.out.println(Modifier.toString(cons.getModifiers())+" "+cons.getName()+"("+(param.length()>0?param.substring(0, param.length()-1):param)+")"); }
System.out.println("----------------start methods print-------------------");
Method[] methods = clazz.getDeclaredMethods();//獲取該類中申明的方法 包括private方法 但不包括父類的方法
for(Method met:methods){String param ="";for(Class str:met.getParameterTypes()){param +=str+",";}  c++

System.out.println(Modifier.toString(met.getModifiers())+" "+met.getReturnType()+" "+met.getName()+"("+(param.length()>0?param.substring(0, param.length()-1):param)+")");}
System.out.println("----------------start parameters print-------------------");
Field[] fields = clazz.getDeclaredFields();//獲取該類中申明的成員變量 包括private成員變量, 但不包括父類的成員變量
for(Field fil : fields){System.out.println(Modifier.toString(fil.getModifiers())+" "+fil.getType()+" "+fil.getName());}
編程

                }設計模式

原文地址:http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html數組

本篇文章依舊採用小例子來講明,由於我始終覺的,案例驅動是最好的,要否則只看理論的話,看了也不懂,不過建議你們在看完文章以後,在回過頭去看看理論,會有更好的理解。app

下面開始正文。框架

【案例1】經過一個對象得到完整的包名和類名ide

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Reflect;
  
/**
  * 經過一個對象得到完整的包名和類名
  * */
class Demo{
     //other codes...
}
  
class hello{
     public static void main(String[] args) {
         Demo demo= new Demo();
         System.out.println(demo.getClass().getName());
     }
}

【運行結果】:Reflect.Demo函數

添加一句:全部類的對象其實都是Class的實例。

【案例2】實例化Class類對象

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package Reflect;
class Demo{
     //other codes...
}
  
class hello{
     public static void main(String[] args) {
         Class<?> demo1= null ;
         Class<?> demo2= null ;
         Class<?> demo3= null ;
         try {
             //通常儘可能採用這種形式
             demo1=Class.forName( "Reflect.Demo" );
         } catch (Exception e){
             e.printStackTrace();
         }
         demo2= new Demo().getClass();
         demo3=Demo. class ;
          
         System.out.println( "類名稱   " +demo1.getName());
         System.out.println( "類名稱   " +demo2.getName());
         System.out.println( "類名稱   " +demo3.getName());
          
     }
}

【運行結果】:

類名稱   Reflect.Demo

類名稱   Reflect.Demo

類名稱   Reflect.Demo

【案例3】經過Class實例化其餘類的對象

經過無參構造實例化對象

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package Reflect;
  
class Person{
      
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this .name = name;
     }
     public int getAge() {
         return age;
     }
     public void setAge( int age) {
         this .age = age;
     }
     @Override
     public String toString(){
         return "[" + this .name+ "  " + this .age+ "]" ;
     }
     private String name;
     private int age;
}
  
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         Person per= null ;
         try {
             per=(Person)demo.newInstance();
         } catch (InstantiationException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         } catch (IllegalAccessException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         per.setName( "Rollen" );
         per.setAge( 20 );
         System.out.println(per);
     }
}

【運行結果】:

[Rollen  20]

可是注意一下,當咱們把Person中的默認的無參構造函數取消的時候,好比本身定義只定義一個有參數的構造函數以後,會出現錯誤:

好比我定義了一個構造函數:

?
1
2
3
4
public Person(String name, int age) {
         this .age=age;
         this .name=name;
     }

而後繼續運行上面的程序,會出現:

java.lang.InstantiationException: Reflect.Person

    at java.lang.Class.newInstance0(Class.java:340)

    at java.lang.Class.newInstance(Class.java:308)

    at Reflect.hello.main(hello.java:39)

Exception in thread "main" java.lang.NullPointerException

    at Reflect.hello.main(hello.java:47)

因此你們之後再編寫使用Class實例化其餘類的對象的時候,必定要本身定義無參的構造函數

 

【案例】經過Class調用其餘類中的構造函數(也能夠經過這種方式經過Class建立其餘類的對象)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package Reflect;
  
import java.lang.reflect.Constructor;
  
class Person{
      
     public Person() {
          
     }
     public Person(String name){
         this .name=name;
     }
     public Person( int age){
         this .age=age;
     }
     public Person(String name, int age) {
         this .age=age;
         this .name=name;
     }
     public String getName() {
         return name;
     }
     public int getAge() {
         return age;
     }
     @Override
     public String toString(){
         return "[" + this .name+ "  " + this .age+ "]" ;
     }
     private String name;
     private int age;
}
  
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         Person per1= null ;
         Person per2= null ;
         Person per3= null ;
         Person per4= null ;
         //取得所有的構造函數
         Constructor<?> cons[]=demo.getConstructors();
         try {
             per1=(Person)cons[ 0 ].newInstance();
             per2=(Person)cons[ 1 ].newInstance( "Rollen" );
             per3=(Person)cons[ 2 ].newInstance( 20 );
             per4=(Person)cons[ 3 ].newInstance( "Rollen" , 20 );
         } catch (Exception e){
             e.printStackTrace();
         }
         System.out.println(per1);
         System.out.println(per2);
         System.out.println(per3);
         System.out.println(per4);
     }
}

【運行結果】:

[null  0]

[Rollen  0]

[null  20]

[Rollen  20]

【案例】 

返回一個類實現的接口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package Reflect;
  
interface China{
     public static final String name= "Rollen" ;
     public static  int age= 20 ;
     public void sayChina();
     public void sayHello(String name, int age);
}
  
class Person implements China{
     public Person() {
          
     }
     public Person(String sex){
         this .sex=sex;
     }
     public String getSex() {
         return sex;
     }
     public void setSex(String sex) {
         this .sex = sex;
     }
     @Override
     public void sayChina(){
         System.out.println( "hello ,china" );
     }
     @Override
     public void sayHello(String name, int age){
         System.out.println(name+ "  " +age);
     }
     private String sex;
}
  
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         //保存全部的接口
         Class<?> intes[]=demo.getInterfaces();
         for ( int i = 0 ; i < intes.length; i++) {
             System.out.println( "實現的接口   " +intes[i].getName());
         }
     }
}

【運行結果】:

實現的接口   Reflect.China

(注意,如下幾個例子,都會用到這個例子的Person類,因此爲節省篇幅,此處再也不粘貼Person的代碼部分,只粘貼主類hello的代碼)

【案例】:取得其餘類中的父類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         //取得父類
         Class<?> temp=demo.getSuperclass();
         System.out.println( "繼承的父類爲:   " +temp.getName());
     }
}

【運行結果】

繼承的父類爲:   java.lang.Object

【案例】:得到其餘類中的所有構造函數

這個例子須要在程序開頭添加import java.lang.reflect.*;

而後將主類編寫爲:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         Constructor<?>cons[]=demo.getConstructors();
         for ( int i = 0 ; i < cons.length; i++) {
             System.out.println( "構造方法:  " +cons[i]);
         }
     }
}

【運行結果】:

構造方法:  public Reflect.Person()

構造方法:  public Reflect.Person(java.lang.String)

可是細心的讀者會發現,上面的構造函數沒有public 或者private這一類的修飾符

下面這個例子咱們就來獲取修飾符

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         Constructor<?>cons[]=demo.getConstructors();
         for ( int i = 0 ; i < cons.length; i++) {
             Class<?> p[]=cons[i].getParameterTypes();
             System.out.print( "構造方法:  " );
             int mo=cons[i].getModifiers();
             System.out.print(Modifier.toString(mo)+ " " );
             System.out.print(cons[i].getName());
             System.out.print( "(" );
             for ( int j= 0 ;j<p.length;++j){
                 System.out.print(p[j].getName()+ " arg" +i);
                 if (j<p.length- 1 ){
                     System.out.print( "," );
                 }
             }
             System.out.println( "){}" );
         }
     }
}

【運行結果】:

構造方法:  public Reflect.Person(){}

構造方法:  public Reflect.Person(java.lang.String arg1){}

有時候一個方法可能還有異常,呵呵。下面看看:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class hello{
     public static void main(String[] args) {
         Class<?> demo= null ;
         try {
             demo=Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         Method method[]=demo.getMethods();
         for ( int i= 0 ;i<method.length;++i){
             Class<?> returnType=method[i].getReturnType();
             Class<?> para[]=method[i].getParameterTypes();
             int temp=method[i].getModifiers();
             System.out.print(Modifier.toString(temp)+ " " );
             System.out.print(returnType.getName()+ "  " );
             System.out.print(method[i].getName()+ " " );
             System.out.print( "(" );
             for ( int j= 0 ;j<para.length;++j){
                 System.out.print(para[j].getName()+ " " + "arg" +j);
                 if (j<para.length- 1 ){
                     System.out.print( "," );
                 }
             }
             Class<?> exce[]=method[i].getExceptionTypes();
             if (exce.length> 0 ){
                 System.out.print( ") throws " );
                 for ( int k= 0 ;k<exce.length;++k){
                     System.out.print(exce[k].getName()+ " " );
                     if (k<exce.length- 1 ){
                         System.out.print( "," );
                     }
                 }
             } else {
                 System.out.print( ")" );
             }
             System.out.println();
         }
     }
}

【運行結果】:

public java.lang.String  getSex ()

public void  setSex (java.lang.String arg0)

public void  sayChina ()

public void  sayHello (java.lang.String arg0,int arg1)

public final native void  wait (long arg0) throws java.lang.InterruptedException

public final void  wait () throws java.lang.InterruptedException

public final void  wait (long arg0,int arg1) throws java.lang.InterruptedException

public boolean  equals (java.lang.Object arg0)

public java.lang.String  toString ()

public native int  hashCode ()

public final native java.lang.Class  getClass ()

public final native void  notify ()

public final native void  notifyAll ()

【案例】接下來讓咱們取得其餘類的所有屬性吧,最後我講這些整理在一塊兒,也就是經過class取得一個類的所有框架

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class hello {
     public static void main(String[] args) {
         Class<?> demo = null ;
         try {
             demo = Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         System.out.println( "===============本類屬性========================" );
         // 取得本類的所有屬性
         Field[] field = demo.getDeclaredFields();
         for ( int i = 0 ; i < field.length; i++) {
             // 權限修飾符
             int mo = field[i].getModifiers();
             String priv = Modifier.toString(mo);
             // 屬性類型
             Class<?> type = field[i].getType();
             System.out.println(priv + " " + type.getName() + " "
                     + field[i].getName() + ";" );
         }
         System.out.println( "===============實現的接口或者父類的屬性========================" );
         // 取得實現的接口或者父類的屬性
         Field[] filed1 = demo.getFields();
         for ( int j = 0 ; j < filed1.length; j++) {
             // 權限修飾符
             int mo = filed1[j].getModifiers();
             String priv = Modifier.toString(mo);
             // 屬性類型
             Class<?> type = filed1[j].getType();
             System.out.println(priv + " " + type.getName() + " "
                     + filed1[j].getName() + ";" );
         }
     }
}

【運行結果】:

===============本類屬性========================

private java.lang.String sex;

===============實現的接口或者父類的屬性========================

public static final java.lang.String name;

public static final int age;

【案例】其實還能夠經過反射調用其餘類中的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class hello {
     public static void main(String[] args) {
         Class<?> demo = null ;
         try {
             demo = Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         try {
             //調用Person類中的sayChina方法
             Method method=demo.getMethod( "sayChina" );
             method.invoke(demo.newInstance());
             //調用Person的sayHello方法
             method=demo.getMethod( "sayHello" , String. class , int . class );
             method.invoke(demo.newInstance(), "Rollen" , 20 );
              
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
}

  【運行結果】:

hello ,china

Rollen  20

【案例】調用其餘類的set和get方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class hello {
     public static void main(String[] args) {
         Class<?> demo = null ;
         Object obj= null ;
         try {
             demo = Class.forName( "Reflect.Person" );
         } catch (Exception e) {
             e.printStackTrace();
         }
         try {
          obj=demo.newInstance();
         } catch (Exception e) {
             e.printStackTrace();
         }
         setter(obj, "Sex" , "男" ,String. class );
         getter(obj, "Sex" );
     }
  
     /**
      * @param obj
      *            操做的對象
      * @param att
      *            操做的屬性
      * */
     public static void getter(Object obj, String att) {
         try {
             Method method = obj.getClass().getMethod( "get" + att);
             System.out.println(method.invoke(obj));
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
  
     /**
      * @param obj
      *            操做的對象
      * @param att
      *            操做的屬性
      * @param value
      *            設置的值
      * @param type
      *            參數的屬性
      * */
     public static void setter(Object obj, String att, Object value,
             Class<?> type) {
         try {
             Method method = obj.getClass().getMethod( "set" + att, type);
             method.invoke(obj, value);
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
} // end class

【運行結果】:

 【案例】經過反射操做屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class hello {
     public static void main(String[] args) throws Exception {
         Class<?> demo = null ;
         Object obj = null ;
  
         demo = Class.forName( "Reflect.Person" );
         obj = demo.newInstance();
  
         Field field = demo.getDeclaredField( "sex" );
         field.setAccessible( true );
         field.set(obj, "男" );
         System.out.println(field.get(obj));
     }
} // end class

【案例】經過反射取得並修改數組的信息:

?
1
2
3
4
5
6
7
8
9
10
11
12
import java.lang.reflect.*;
class hello{
     public static void main(String[] args) {
         int [] temp={ 1 , 2 , 3 , 4 , 5 };
         Class<?>demo=temp.getClass().getComponentType();
         System.out.println( "數組類型: " +demo.getName());
         System.out.println( "數組長度  " +Array.getLength(temp));
         System.out.println( "數組的第一個元素: " +Array.get(temp, 0 ));
         Array.set(temp, 0 , 100 );
         System.out.println( "修改以後數組第一個元素爲: " +Array.get(temp, 0 ));
     }
}

【運行結果】:

數組類型: int

數組長度  5

數組的第一個元素: 1

修改以後數組第一個元素爲: 100

【案例】經過反射修改數組大小

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class hello{
     public static void main(String[] args) {
         int [] temp={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
         int [] newTemp=( int [])arrayInc(temp, 15 );
         print(newTemp);
         System.out.println( "=====================" );
         String[] atr={ "a" , "b" , "c" };
         String[] str1=(String[])arrayInc(atr, 8 );
         print(str1);
     }
      
     /**
      * 修改數組大小
      * */
     public static Object arrayInc(Object obj, int len){
         Class<?>arr=obj.getClass().getComponentType();
         Object newArr=Array.newInstance(arr, len);
         int co=Array.getLength(obj);
         System.arraycopy(obj, 0 , newArr, 0 , co);
         return newArr;
     }
     /**
      * 打印
      * */
     public static void print(Object obj){
         Class<?>c=obj.getClass();
         if (!c.isArray()){
             return ;
         }
         System.out.println( "數組長度爲: " +Array.getLength(obj));
         for ( int i = 0 ; i < Array.getLength(obj); i++) {
             System.out.print(Array.get(obj, i)+ " " );
         }
     }
}

【運行結果】:

數組長度爲: 15

1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================

數組長度爲: 8

a b c null null null null null

動態代理

【案例】首先來看看如何得到類加載器:

?
1
2
3
4
5
6
7
8
9
class test{
      
}
class hello{
     public static void main(String[] args) {
         test t= new test();
         System.out.println( "類加載器  " +t.getClass().getClassLoader().getClass().getName());
     }
}

【程序輸出】:

類加載器  sun.misc.Launcher$AppClassLoader

其實在java中有三種類類加載器。

1)Bootstrap ClassLoader 此加載器採用c++編寫,通常開發中不多見。

2)Extension ClassLoader 用來進行擴展類的加載,通常對應的是jre\lib\ext目錄中的類

3)AppClassLoader 加載classpath指定的類,是最經常使用的加載器。同時也是java中默認的加載器。

若是想要完成動態代理,首先須要定義一個InvocationHandler接口的子類,已完成代理的具體操做。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package Reflect;
import java.lang.reflect.*;
  
//定義項目接口
interface Subject {
     public String say(String name, int age);
}
  
// 定義真實項目
class RealSubject implements Subject {
     @Override
     public String say(String name, int age) {
         return name + "  " + age;
     }
}
  
class MyInvocationHandler implements InvocationHandler {
     private Object obj = null ;
  
     public Object bind(Object obj) {
         this .obj = obj;
         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
                 .getClass().getInterfaces(), this );
     }
  
     @Override
     public Object invoke(Object proxy, Method method, Object[] args)
             throws Throwable {
         Object temp = method.invoke( this .obj, args);
         return temp;
     }
}
  
class hello {
     public static void main(String[] args) {
         MyInvocationHandler demo = new MyInvocationHandler();
         Subject sub = (Subject) demo.bind( new RealSubject());
         String info = sub.say( "Rollen" , 20 );
         System.out.println(info);
     }
}

【運行結果】:

Rollen  20

類的生命週期

在一個類編譯完成以後,下一步就須要開始使用類,若是要使用一個類,確定離不開JVM。在程序執行中JVM經過裝載,連接,初始化這3個步驟完成。

類的裝載是經過類加載器完成的,加載器將.class文件的二進制文件裝入JVM的方法區,而且在堆區建立描述這個類的java.lang.Class對象。用來封裝數據。可是同一個類只會被類裝載器裝載之前

連接就是把二進制數據組裝爲能夠運行的狀態。

 

連接分爲校驗,準備,解析這3個階段

校驗通常用來確認此二進制文件是否適合當前的JVM(版本),

準備就是爲靜態成員分配內存空間,。並設置默認值

解析指的是轉換常量池中的代碼做爲直接引用的過程,直到全部的符號引用均可以被運行程序使用(創建完整的對應關係)

完成以後,類型也就完成了初始化,初始化以後類的對象就能夠正常使用了,直到一個對象再也不使用以後,將被垃圾回收。釋放空間。

當沒有任何引用指向Class對象時就會被卸載,結束類的生命週期

將反射用於工廠模式

先來看看,若是不用反射的時候,的工廠模式吧:

http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
  * @author Rollen-Holt 設計模式之 工廠模式
  */
  
interface fruit{
     public abstract void eat();
}
  
class Apple implements fruit{
     public void eat(){
         System.out.println( "Apple" );
     }
}
  
class Orange implements fruit{
     public void eat(){
         System.out.println( "Orange" );
     }
}
  
// 構造工廠類
// 也就是說之後若是咱們在添加其餘的實例的時候只須要修改工廠類就好了
class Factory{
     public static fruit getInstance(String fruitName){
         fruit f= null ;
         if ( "Apple" .equals(fruitName)){
             f= new Apple();
         }
         if ( "Orange" .equals(fruitName)){
             f= new Orange();
         }
         return f;
     }
}
class hello{
     public static void main(String[] a){
         fruit f=Factory.getInstance( "Orange" );
         f.eat();
     }
  
}

這樣,當咱們在添加一個子類的時候,就須要修改工廠類了。若是咱們添加太多的子類的時候,改的就會不少。

如今咱們看看利用反射機制:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package Reflect;
  
interface fruit{
     public abstract void eat();
}
  
class Apple implements fruit{
     public void eat(){
         System.out.println( "Apple" );
     }
}
  
class Orange implements fruit{
     public void eat(){
         System.out.println( "Orange" );
     }
}
  
class Factory{
     public static fruit getInstance(String ClassName){
         fruit f= null ;
         try {
             f=(fruit)Class.forName(ClassName).newInstance();
         } catch (Exception e) {
             e.printStackTrace();
         }
         return f;
     }
}
class hello{
     public static void main(String[] a){
         fruit f=Factory.getInstance( "Reflect.Apple" );
         if (f!= null ){
             f.eat();
         }
     }
}

如今就算咱們添加任意多個子類的時候,工廠類就不須要修改。

 

上面的愛嗎雖然能夠經過反射取得接口的實例,可是須要傳入完整的包和類名。並且用戶也沒法知道一個接口有多少個可使用的子類,因此咱們經過屬性文件的形式配置所須要的子類。

下面咱們來看看: 結合屬性文件的工廠模式

首先建立一個fruit.properties的資源文件,

內容爲:

?
1
2
apple=Reflect.Apple
orange=Reflect.Orange

 而後編寫主類代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package Reflect;
  
import java.io.*;
import java.util.*;
  
interface fruit{
     public abstract void eat();
}
  
class Apple implements fruit{
     public void eat(){
         System.out.println( "Apple" );
     }
}
  
class Orange implements fruit{
     public void eat(){
         System.out.println( "Orange" );
     }
}
  
//操做屬性文件類
class init{
     public static Properties getPro() throws FileNotFoundException, IOException{
         Properties pro= new Properties();
         File f= new File( "fruit.properties" );
         if (f.exists()){
             pro.load( new FileInputStream(f));
         } else {
             pro.setProperty( "apple" , "Reflect.Apple" );
             pro.setProperty( "orange" , "Reflect.Orange" );
             pro.store( new FileOutputStream(f), "FRUIT CLASS" );
         }
         return pro;
     }
}
  
class Factory{
     public static fruit getInstance(String ClassName){
         fruit f= null ;
         try {
             f=(fruit)Class.forName(ClassName).newInstance();
         } catch (Exception e) {
             e.printStackTrace();
         }
         return f;
     }
}
class hello{
     public static void main(String[] a) throws FileNotFoundException, IOException{
         Properties pro=init.getPro();
         fruit f=Factory.getInstance(pro.getProperty( "apple" ));
         if (f!= null ){
             f.eat();
         }
     }
}

【運行結果】:Apple

相關文章
相關標籤/搜索