反射基礎,沒有理論,只有使用

public class DemoClass {
    private String nickName;
    public  int num = 3;
    public int add(int a,int b){
        return a + b;
    }
    public int sub(int a,int b){
        return a - b;
    }
    static {
        System.out.println("DemoClass靜態代碼塊");
    }
    {
        System.out.println("DemoClass動態代碼塊");
    }
    public DemoClass(){}
    public DemoClass(String string){
        System.out.println("DemoClass構造方法");
    }
    public String getNickName() {
        return nickName;
    }
    public void setNickName(String name) {
        this.nickName = name;
    }
    public int getNum() {
        return num;
    }
    private void  testMethod(){
        System.out.println("靜態方法");
    }

  1. 獲取類對象

    1. 直接調用某一個類的class屬性(不知道這樣說合適不合適)
    2. 調用某一個對象的getClass方法
    3. 調用Class類的靜態方法forName
    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> classDemo = DemoClass.class;//class demo.DemoClass//不會調用任何方法
            Class<?> classNew = new DemoClass().getClass();//class demo.DemoClass 靜態代碼塊和動態代碼塊還有構造方法都會執行
            Class<?> forName = Class.forName("demo.DemoClass");//class demo.ReflectDemo,只會調用靜態代碼塊
            System.out.println(forName);//class demo.DemoClass
            System.out.println(classDemo == classNew);//true
            System.out.println(classNew == forName);//true
            System.out.println(forName == classDemo);//true
        }
    }
    
  2. 獲取類實例

    1. 通過newInstance,這種是調用單獨無參構造函數,所以如果沒有無參構造函數就會異常
    2. 獲取指定的構造函數,再通過指定的構造函數的newInstance創建實例
    public class ReflectDemo {
        public static void main(String[] args) throws ClassNotFoundException {
            Class<?> forName = Class.forName("demo.DemoClass");
            try {
                Object o = forName.newInstance();//這種每次獲取的都是同一個對象,class必須有無參構造函數,否則會報錯
                System.out.println(o);//demo.ReflectDemo@14ae5a
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
            try {
                Constructor<?> constructor = forName.getConstructor(String.class);
                Object parade = constructor.newInstance("parade");
                Object year = constructor.newInstance("year");
                System.out.println(parade);//demo.DemoClass@7f31245a
                System.out.println(year);//demo.DemoClass@6d6f6e28
            } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    
  3. 獲取屬性

    1. getFields->不能獲取私有屬性

    2. getDeclaredFields->可以獲取私有屬性

      public static void main(String[] args) throws ClassNotFoundException {
          Class<?> forName = Class.forName("demo.DemoClass");//class demo.ReflectDemo,只會調用靜態代碼塊
         
          try {
              Field name = forName.getField("name");//name是私有,則會拋異常
          } catch (NoSuchFieldException e) {
              e.printStackTrace();
          }
          Field[] fields = forName.getFields();//獲取所有非私有屬性
          for (Field field : fields) {
              System.out.println(field.getName());
          }
          
          try {
              Field name = forName.getDeclaredField("name");
              System.out.println(name);
          } catch (NoSuchFieldException e) {
              e.printStackTrace();
          }
          Field[] declaredFields = forName.getDeclaredFields();//獲取所有屬性
          for (Field declaredField : declaredFields) {
              System.out.println(declaredField.getName());
          }
      }
      
    3. 屬性賦值

      public static void main(String[] args) throws ClassNotFoundException {
          Class<?> forName = Class.forName("demo.DemoClass");//class demo.ReflectDemo,只會調用靜態代碼塊
          try {
              Field name = forName.getDeclaredField("nickName");
              DemoClass o = (DemoClass) forName.newInstance();//通過Class對象得到實例對象
              name.setAccessible(true);//將私有屬性設置爲可訪問
              name.set(o,"parade");//給私有屬性賦值
              System.out.println(o.getNickName());//驗證賦值成功
              Field num = forName.getField("num");//非私有屬性賦值
      		num.setInt(o,5);
      		System.out.println(o.getNum());//驗證賦值成功
      		Object o1 = num.get(o);//或者繼續通過反射獲取屬性值
            System.out.println(o1);
          } catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) {
              e.printStackTrace();
          }
         
      }
      
  4. 獲取方法->類似獲取屬性

    1. getMethod->不能獲取私有方法

    2. getDeclaredMethods

      Method[] methods = forName.getMethods();//會得到所有非private方法,包括父類的方法
      for (Method method : methods) {
          System.out.println(method.getName());
      }
      Method[] declaredMethods = forName.getDeclaredMethods();//獲取本類的所有方法,不包括父類
      for (Method declaredMethod : declaredMethods) {
          System.out.println(declaredMethod.getName());
      }
      
    3. 調用方法

      public static void main(String[] args) throws ClassNotFoundException {
          Class<?> forName = Class.forName("demo.DemoClass");//class demo.ReflectDemo,只會調用靜態代碼塊
          try {
              DemoClass demoClass = (DemoClass) forName.newInstance();//調用方法前先要獲得一個實例對象才能調用實例對象的方法
              Method setNickName = forName.getMethod("setNickName", String.class);
              Method getNickName = forName.getMethod("getNickName");
              setNickName.invoke(demoClass, "Are you ok");
              System.out.println(getNickName.invoke(demoClass));
              Method testMethod = forName.getDeclaredMethod("testMethod");
              testMethod.setAccessible(true);//調用私有方法同樣要設置可訪問
              testMethod.invoke(demoClass);
          } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
              e.printStackTrace();
          }
      }
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章