反射

一.枚舉是Java SE5.0以後纔有的類型,下面通過一個實例來說明其中的用法      

public class TestEnum {
    
    public static void main(String[] args) {        
        WeekDay wd = WeekDay.FRI;
        //枚舉對象的方法
        System.out.println(wd.name());
        //在枚舉列表中的位置
        System.out.println(wd.ordinal());
        
        //枚舉類中的靜態方法
        System.out.println(WeekDay.valueOf(“MON“));//返回字字符串參數對應的枚舉
        //遍歷枚舉類,
        for(WeekDay w : WeekDay.values()){ //靜態方法values()返回一個WeekDay數組
            System.out.println(w);
        }        
    }
    /* 枚舉也可以象一般的類一樣添加方法和屬性,你可以爲它添加靜態和非靜態的屬性或方法,這一切都象你在一般的類中做的那樣. */
    /*還可以有構造方法,但是構造方法必須是私有的即用private修飾*/
    public enum WeekDay{
        //枚舉列表必須卸載最前面,否則編譯出錯
        SUN(1), MON(), TUE, WED, THI, FRI, SAT;        
        
//        構造方法必須是私有的,並且可以在枚舉列表中直接調用
        private WeekDay(){
            System.out.println(“first”);
        }        
        private WeekDay(int day){
            System.out.println(“second”);
        }
    }

    
   
交通燈的一個枚舉類:
   

 public enum TrafficLamp{
        RED(30) {
            public TrafficLamp nextLamp() {
                return GREEN;
            }
        }, 
        GREEN(45) {
            public TrafficLamp nextLamp() {
                return YELLOW;
            }
        }, 
        YELLOW(5) {
            public TrafficLamp nextLamp() {
                return RED;
            }
        };
        //抽象方法,也可以定義非常想方法
        public abstract TrafficLamp nextLamp();    
        
       //可以定義屬性變量
        private int time;
        private TrafficLamp(int time){
            this.time = time;
        }    
    }  

  二 、反射的基石——Class類

Java程序中的各個Java類屬於同一類事物,描述這類事物的Java類就是Class類。

Class類代表一類什麼樣的事物呢?

Person p1 = new Person();

Person p2 = new Person();

Class類的對象代表的是一份字節碼,就是編譯之後的那份類所對應的字節碼。

得到這份字節碼的方式:共有三種

Class cls1 = p1.getClass(); //調用對象的getClass()方法可以得到

Class cls2  =String.class; //用類名.class獲取一個類的字節碼

Class cls3 = Class.forName(“java.util.Date”); //通過Class類的靜態方法forName()獲得

九個預定義類型的實例對象:基本的 Java 類型(booleanbytecharshortintlongfloat 和double)和關鍵字void 也表示爲Class對象。基本類型的字節碼獲取方式只有一種就是類名.class。例如int.class;void.class

數組也是一種Class的實例對象。

總之,只要是在源程序中出現的類型,都有各自的Class實例對象,例如int[],void

三、反射

    什麼是反射:反射就是把Java類中的各種成分映射成相應的Java類。例如:一個Java類中用一個Class類的對象來表示,一個類中的組成部分:成員變量,方法,構造方法,包等信息也用一個個的Java類來表示,就像汽車是一個類,汽車中的發動機,變速箱等也是一個個類。表示Java類的Class類顯然要提供一系列的方式,來獲得其中的變量,方法,構造方法,修飾符,包等信息,謝謝信息就是用相應類的實例對象來表示的,它們是:Field、Method、Contrctor、Package等等。

列子:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class ReflectTest {
      public static void main(String[] args) throws Exception{
            String str1 = “abc”;
           //三種方式得到Class類,即獲得字節碼
            Class cls1 = str1.getClass();//調用對象的getClass()方法
            Class cls2 = String.class; //類名.class方式
           Class cls3 = Class.forName(“java.lang.String”);//Class類的forName()方法
           //驗證得到的是否爲同一份字節碼,輸出結果都爲true
          System.out.println(cls1 == cls2);
          System.out.println(cls1 == cls3);
          //判斷是否爲基本類型的字節碼對象
          System.out.println(cls1.isPrimitive());
          //基本數據類型的的字節碼獲取只有一種方式,類名.class方式
          System.out.println(int.class.isPrimitive());
          //數組也是一種特定的類型
          System.out.println(int[].class.isPrimitive());//結果爲false
          System.out.println(int[].class.isArray());//結果爲true
           //構造方法的反射
           //Constructor類代表某個類中的一個構造方法
          //得到參數類型爲StringBuffer的String的構造方法
          Constructor<String> constructor1 = String.class.getConstructor(StringBuffer.class);
          //用反射的方式得到new String(new StringBuffer(“abc”))的效果
          String str2 = (String)constructor1.newInstance(new StringBuffer(“abc”));
          System.out.println(str2.charAt(2));
          ReflectPoint pt1 = new ReflectPoint(3,5);
          Field fieldY = pt1.getClass().getField(“y”);//獲取字段,fieldY代表一個變量
         //fieldY不是對象身上的變量,而是類上的,要用它去取某個對象上對應的值要調用fieldY的get(obj)方法
          System.out.println(fieldY.get(pt1));//結果輸出爲5
         //因爲ReflectPoint中的x是private修飾的,無法用fieldX.get(pt1)獲取,這是需要用getDeclareField(“x”);
         Field fieldX = pt1.getClass().getDeclaredField(“x”);
          //但是由於是私有的,只允許自己訪問,所以還要設置它的訪問權限
          fieldX.setAccessible(true);//這種方式一般就稱爲“暴力反射”
         System.out.println(fieldX.get(pt1));
          changeStringValue(pt1);
          System.out.println(pt1.toString());
     }
     private static void changeStringValue(Object obj) throws Exception{
           Field[] fields = obj.getClass().getFields();
          for(Field field : fields){
                           //如果字節碼相同,則替換
                       if(field.getType() == String.class){
                                    String oldValue = (String)field.get(obj);
                                    String newValue = oldValue.replace(‘b’, ‘a’);
                                  //換取之後要,把新字段設置到對象中去
                                   field.set(obj, newValue);//吧newValue設置到obj對象中
                       }
           }
     }
}


用到的RelfectPoint類

public class ReflectPoint {
              private int x;
              public int y;
              public String str1 = “ball”;
              public String str2 = “ballball”;
              public String str3 = “itcase”;
              public ReflectPoint(int x, int y) {
                          super();
                          this.x = x;
                          this.y = y;
              }
             //複寫時@Override,你的方法名寫錯了的時候編譯器會自動報錯</span>
            @ Override
             public String toString(){
                   return str1+”:”+str2+”:”+str3;
            }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章