1. 程式人生 > >利用反射建立物件的一些問題

利用反射建立物件的一些問題

所要構造的類如下所示

 package GetClass;
        
  public class People{
        private  String name;
    public People(){}
    private People(String name){
            this.name =name;
        }
    public String getName() {
            return name; }
    public void setName(String name) {
            this.name = name; }
    
    @Override 
    public String toString() {
            return new String("姓名:"+name); }
    }

平常我們都是用new來構造大概這樣

 People people = new People("蜘蛛俠");

但是還有種構造方法稱之為反射

try{
           String classname = "GetClass.People";
            Class pClass = Class.forName(classname);
           Constructor c = pClass.getConstructor();
            People p1 = (People) c.newInstance();
           p1.setName("毒液");
      }catch(Exception e){
            e.printStackTrace(); }

這裡出了一些小小的問題
1.forname()中的引數只能是public的,而且一個完整的類名需要包括包名。否則會丟擲ClassNoFoundException異常。
2.getConstructor()方法只接受預設構造(非無參構造)而如果想傳入有參的構造需要呼叫getDeclaredConstructor()函式。方法如下:

 Constructor c = pClass.getDeclaredConstructor(String.class);
 People p1 = (People) c.newInstance("毒液");

又出現的一點問題該方法是私有無法呼叫

c.setAccessible(true);

通過該方法可以調取私有,值為 true 反射的物件在使用時取消訪問檢查。(不是true就能訪問false就不能訪問,true只是關閉了訪問檢查的開關)

其實private不代表安全,只是告訴你這個是private的不建議你訪問,如果出了事你得自己負責。c.setAccess ible(true)的意思是我覺得你知道你在幹什麼,那就去做吧。
就像一個女孩穿著超短裙,下面套著安全褲。超短裙就是public是可以給你隨便看,但是下面的private就不是一般人看得了的。看了出了事可是要負責的。

運用反射不光可以構造物件,也可以修改物件的欄位方法如下:

try{
 Field fd=people.getClass().getDeclaredField("name");
 fd.setAccessible(true);
 fd.set(people,"綠巨人");
 System.out.println(people);
 }catch (Exception e){e.getStackTrace();}

注意:getField 只能獲取public的,包括從父類繼承來的欄位。getDeclaredField 可以獲取本類所有的欄位,包括private的,但是不能獲取繼承來的欄位。(獲取是獲取,就算獲取的private也不能直接訪問)

當然反射也可以呼叫方法:

try{//前面的引數是方法名後面的引數是引數型別
   Method md = people.getClass().getMethod("setName", String.class);
   //對people物件呼叫方法
  md.invoke(people,"金剛狼");
  System.out.println(people);
}catch (Exception e){e.getStackTrace();}

總結一下反射就是通過一個已知的物件(類,普通),呼叫他們的屬性和方法。