Java 反射

一切皆爲對象,是Java的核心概念;java

從這個概念出發,咱們不由要問類是否是對象?若是類也是對象,類又是誰的實例對象呢?函數

答案是確定的,類也是對象,類是java.lang.Class(如下簡稱Class)的實例對象,Class也被成爲類的類類型。spa

假設有類Student,以下code

class Student{
    private int id;
    private String name;

    //get,set方法          
}

 

獲取類的類類型有三種方法,分別以下:對象

1.  Class c1 = Student.class;blog

2.  Student  stu = new Student();繼承

      Class cl = stu.getClass();get

3.  Class cl = Class.forName("類全名");io

 

咱們能夠經過類的類類型建立這個類的實例對象,前提是這個類有一個無參的構造函數,以下編譯

Student  stu = (Student) c1.newInstance();

 

動態加載的概念

  編譯時加載類是靜態加載類,new 對象
  運行時加載類時動態加載類

 

反射使用

//獲取類的名稱
String className = cl.getName();
//獲取類名稱的簡寫
String classSimpleName = cl.getSimpleName();

/**
 * Method類,方法的對象
 * 一個成員方法就是一個Method對象
 * getMethods() 獲取的是所有public的方法,包括從父類繼承來的
 *getDeclaredMethods()獲取本身聲明的所有方法(public private protect),不獲 
 *   取父類
 */
Method[] methods = cl.getMethods();
for (Method method : methods){
        //獲得方法的返回類型
        //獲得方法返回值的類類型
        Class returnType = method.getReturnType(); 
        //獲得方法名
        String methodName = method.getName();

        //獲取參數類型
        //獲得參數列表的類型的類類型
        Class[] paras = method.getParameterTypes();
        for (Class c : paras){
                System.out.print(c.getName());
        }
}

 

經過反射獲取變量

/**
 * 成員變量也是對象
 * java.lang.reflect.Field
 * Field 封裝了成員變量的操做
 * getFields() 獲取全部的public成員變量信息
 * getDeclaredFields() 獲取該類本身聲明的全部成員變量信息
 */
Field[] fields = cl.getDeclaredFields();
for (Field field : fields){
//變量的修飾符
//獲得成員變量的類型的類類型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//獲得成員變量的名稱
String fieldName = field.getName();

//打印變量類型和變量名
System.out.println(typeName + " " + fieldName);
}

 

打印構造函數信息

/**
 * 構造函數也是對象
 * java.lang.reflect.Constructor 中封裝了構造函數的信息
 * getConstructors() 獲取全部的public的構造函數
 * getDeclaredConstructors() 獲取全部的構造函數
 */
/*Constructor[] cs = cl.getConstructors();*/
Constructor[] cs = cl.getDeclaredConstructors();
for (Constructor c : cs){
        //獲取構造函數名稱
        c.getName();
        //獲取構造函數的類型的類類型
        c.getParameterTypes();
}

 

方法反射

/**
 * 方法的反射
 * 方法的名稱和方法的參數列表能夠惟一肯定一個方法
 * 方法的反射操做
 * Method.invoke(對象, 參數列表)
 */
public static void main(String[] args) throws Exception{
         A a = new A();

         //獲取print(int, int)方法
         //1. 首先獲取類的類類型
         Class cl = a.getClass();
         /**
          * 2. 獲取方法,名稱和參數列表肯定惟一方法
          * getMethod() 獲取的是public方法
          * getDeclaredMethod() 獲取所有本身聲明的方法
          */
         Method method = cl.getMethod("print", new Class[]{int.class, int.class});

         //3. 方法的反射操做,是指用Method對象來進行調用
         //方法沒有返回值返回null,有返回值就返回返回值
         Object object = method.invoke(a, new Object[]{1,2});
         //method.invoke(a, 1, 2);
}

 

使用反射回去對象變量值

public static <T> void printTInfo(T t) throws IllegalAccessException{
        Class cl = t.getClass();

        Field[] fields = cl.getDeclaredFields();
        for (Field field : fields){
            //setAccessible(true)不老是必須的,可是變量爲私有是必須設置
            field.setAccessible(true);
            System.out.println(field.get(t));
        }
}

 

使用反射解析註解

//1.使用類加載器加載類
Class cl = Class.forName("Student");
//2.找到類上面的註解
boolean exist = cl.isAnnotationPresent(Customize.class);

if (exist){
        //3.拿到註解實例
        Customize customize = (Customize)                         
        cl.getAnnotation(Customize.class);
        System.out.println(customize.value());
}

//4.找到方法上的註解
Method[] methods = cl.getMethods();
for (Method method : methods){
        if (method.isAnnotationPresent(Customize.class)){          
                System.out.println(((Customize)method.getAnnotation(Customize.class)).value());
        }
}

//4.1另外一種解析方法
for (Method method : methods){
       Annotation[] annotations = method.getAnnotations();
       for (Annotation annotation : annotations){
               if (annotation instanceof Customize){
                       System.out.println(((Customize) annotation).value());
               }
       }
}

 

註解定義

public @interface Customize {
    String value() default "I am annotation";
}
相關文章
相關標籤/搜索