java反射

獲取到Class對象的三種方法:

 Class clazz = String.class;
Class clazz = javaTest".getClass();
Class clazz = Class.forName("java.lang.String");//常用

獲取到類加載器:

ClassLoader classLoader = ClassLoader.getSystemClassLoader();//系統ClassLoader
classLoader = Class.forName("com.atguigu.java.fanshe.ReflectionTest")
             .getClassLoader();//當然類由哪個ClassLoader加載的

獲取類的方法:

/  1.1 獲取取clazz對應類中的所有方法--方法數組(一)
        //     不能獲取private方法,且獲取從父類繼承來的所有方法
        Method[] methods = clazz.getMethods();
        for(Method method:methods){
            System.out.print(" "+method.getName());
        }
//  1.2.獲取所有方法,包括私有方法 --方法數組(二)
        //  所有聲明的方法,都可以獲取到,且只獲取當前類的方法
        methods = clazz.getDeclaredMethods();
        for(Method method:methods){
            System.out.print(" "+method.getName());
        }
 //  1.3.獲取指定的方法
        //  需要參數名稱和參數列表,無參則不需要寫
        //  對於方法public void setName(String name) {  }
        Method method = clazz.getDeclaredMethod("setName", String.class);
        System.out.println(method);
        //  而對於方法public void setAge(int age) {  }
        method = clazz.getDeclaredMethod("setAge", Integer.class);
        System.out.println(method);
        //  這樣寫是獲取不到的,如果方法的參數類型是int型
        //  如果方法用於反射,那麼要麼int類型寫成Integer: public void setAge(Integer age) {  }
     //  要麼獲取方法的參數寫成int.class

獲取方法的參數和返回值:

System.out.print("方法名:" + method.getName() + " 返回值類型:" + method.getReturnType().getName());
//獲取某個方法的所有參數
            Class[] cls = method.getParameterTypes();
            if (cls.length != 0) {
                for (int j = 0; j < cls.length; j++) {
                    System.out.println(" 方法的參數:" + cls[j].getName());
                }
            } else {
                System.out.println(" ***該方法無參數");
            }

使用方法:

//2.執行方法
        //  invoke第一個參數表示執行哪個對象的方法,剩下的參數是執行方法時需要傳入的參數
        Object obje = clazz.newInstance();
        method.invoke(obje,2);

    //如果一個方法是私有方法,第三步是可以獲取到的,但是這一步卻不能執行
    //私有方法的執行,必須在調用invoke之前加上一句method.setAccessible(true);

獲取到字段field:

@Test
    public void testField() throws Exception{
        String className = "com.atguigu.java.fanshe.Person";        
        Class clazz = Class.forName(className); 
        
        //1.獲取字段
      //  1.1 獲取所有字段 -- 字段數組
        //     可以獲取公用和私有的所有字段,但不能獲取父類字段
        Field[] fields = clazz.getDeclaredFields();
        for(Field field: fields){
            System.out.print(" "+ field.getName());
        }
        System.out.println();
        
        //  1.2獲取指定字段
        Field field = clazz.getDeclaredField("name");
        System.out.println(field.getName());
        
        Person person = new Person("ABC",12);
        
        //2.使用字段
      //  2.1獲取指定對象的指定字段的值
        Object val = field.get(person);
        System.out.println(val);
        
        //  2.2設置指定對象的指定對象Field值
        field.set(person, "DEF");
        System.out.println(person.getName());
        
        //  2.3如果字段是私有的,不管是讀值還是寫值,都必須先調用setAccessible(true)方法
        //     比如Person類中,字段name字段是公用的,age是私有的
        field = clazz.getDeclaredField("age");
        field.setAccessible(true);
        System.out.println(field.get(person));        
    }

但是如果需要訪問父類中的(私有)字段:

/**
     * //創建 className 對應類的對象, 併爲其 fieldName 賦值爲 val
     * //Student繼承自Person,age是Person類的私有字段/
     public void testClassField() throws Exception{
        String className = "com.atguigu.java.fanshe.Student";
        String fieldName = "age"; //可能爲私有, 可能在其父類中. 
        Object val = 20;        
        
        Object obj = null;
        //1.創建className 對應類的對象
        Class clazz = Class.forName(className);
        //2.創建fieldName 對象字段的對象
        Field field = getField(clazz, fieldName);
        //3.爲此對象賦值
        obj = clazz.newInstance();
        setFieldValue(obj, field, val);
        //4.獲取此對象的值
        Object value = getFieldValue(obj,field);
    }
    
    public Object getFieldValue(Object obj, Field field) throws Exception{
        field.setAccessible(true);
        return field.get(obj);
    }

    public void setFieldValue(Object obj, Field field, Object val) throws Exception {
        field.setAccessible(true);
        field.set(obj, val);
    }

    public Field getField(Class clazz, String fieldName) throws Exception {
        Field field = null;
        for(Class clazz2 = clazz; clazz2 != Object.class;clazz2 = clazz2.getSuperclass()){        
                field = clazz2.getDeclaredField(fieldName);
        }
        return field;
    }

使用ClassLoader加載文件:

//src目錄下,直接加載
        InputStream in1 = null;
        in1 = this.getClass().getClassLoader().getResourceAsStream("test1.txt");
        
        //放在內部文件夾,要寫全路徑
        InputStream in2 = null;
        in2 = this.getClass().getClassLoader().getResourceAsStream("com/atguigu/java/fanshe/test2.txt");

例子:

package com.self.test;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class DemoTest {
  public static void main(String[] args) {
    try {
      Class class2 = Class.forName("com.self.entity.Person");
      // 獲取到所有本身的方法名
      Method[] methods = class2.getDeclaredMethods();
      for (Method method : methods) {
        System.out.println(method.getName());
      }
      // 獲取指定method
      Method method = class2.getDeclaredMethod("setSex", String.class);
      // 創建對象
      Object o = class2.newInstance();
      method.invoke(o,"hehe");
      System.out.println(o);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    }


  }
}

借鑑於:https://www.cnblogs.com/tech-bird/p/3525336.html

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