1. 程式人生 > >Java反射總結

Java反射總結

tac tostring ++ random exception 類信息 cat pes ets

反射(java.lang.reflect)用於分析類能力

(一)Class類

1.定義

Java運行時為每一個對象都維護的一個類型標識,用於跟蹤對象所屬的類提供給虛擬機分析調用,而保存這些信息的類就是Class類

(一個Class類對象可以理解為一個類型,這個類型可以是類或基本數據類型int等)

2.作用

通過對象所屬的Class類,我們可以獲取對象類型的數據域,方法,父類等一切類信息,還可以用它來創建實例對象

獲得父類

            //2.獲取父類
            Class superc1=c1.getSuperclass();

創建實例

        //利用反射創建一個實例對象
Class myClass=Class.forName("java.util.Random"); Random random=(Random)myClass.newInstance();

3.獲得Class類的3種途徑

調用Class的靜態方法獲取:Class.forName(String className)

對象調用getClass()方法獲取Class

通過類型名.class獲取,如T.class,T可以是基本數據類型int等,也可以是具體的類如Random.class

        Class myClass=Class.forName("java.util.Random");
        myClass
=new Random().getClass(); myClass=Random.class;

(二)用於描述一個class的三個類:Field,Method,Constructor

Field類代表一個class中的數據域

Method類代表一個class中的方法

Constructor類代表一個class中的構造器

這三個類都繼承Accessible

1.獲取一個類中的Field,Method,Constructor

Class類調用getDeclaredFields()方法獲得該類的所有數據域

Class類調用getDetclaredMethods()方法獲得該類的所有方法

Class類調用getDetclaredConstructors()方法獲得該類的構造器

2.獲得一個Class|Field|Method|Constructor的修飾符

            //Modifier.toString()能夠獲取c1的修飾符public final
            String modifiers=Modifier.toString(c1.getModifiers());        

調用這四個類的getModifiers()方法可以返回一個int,作為參數傳入Modifier.toString(),該方法會根據int判斷出修飾符

3.獲得Field數據域的類型(Class)與Field的名臣

            Class classType=f.getType();
            String name=f.getName();

4.獲取Method的返回類型,Method名稱,Method參數類型

            String returnType=methods[j].getReturnType().getName();
            String methodName=methods[j].getName();
            Class[] paraTypes=methods[j].getParameterTypes();

5.打印一個類的具體信息

package Reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @ClassName ReFlectionTest
 * @Description 利用反射打印Double類的所有方法
 * @Author cherry
 * @Date 2018/6/9 21:22
 * @Update 2018/6/9 21:22
 **/
public class ReFlectionTest{
    public static void main(String[] argv){
        String className="java.lang.Double";
        try{
            //1.獲取Class
            Class c1=Class.forName(className);
            //2.獲取父類
            Class superc1=c1.getSuperclass();
            //3.Modifier.toString()能夠獲取c1的屬性public final
            String modifiers=Modifier.toString(c1.getModifiers());
            //4.打印c1的屬性
            if(modifiers.length()>0)System.out.print(modifiers+" ");
            //5.打印c1的類名
            System.out.print("class "+className);
            //6.若有繼承則打印
            if(superc1!=null&&superc1!=Object.class)System.out.print("extends "
                    +superc1.getName());
            //7.打印中括號
            System.out.print("\n{\n");
            //8.打印域
            printFields(c1);
            //9.打印構造器
            printConstructors(c1);
            //10.打印方法
            printMethods(c1);
            //11.打印中括號
            System.out.print("\n}\n");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }

    /**
     * 打印域
     * @param c1
     */
    public static void printFields(Class c1){
        //1.獲得所有域
        Field[] fields=c1.getFields();
        //2.遍歷打印
        for(Field f:fields){
            Class classType=f.getType();
            String name=f.getName();
            //3.打印進位符
            System.out.print("   ");
            //4.打印屬性
            String modifiers=Modifier.toString(f.getModifiers());
            if(modifiers.length()>0)System.out.print(modifiers+" ");
            System.out.println(classType+" "+name+";");
        }
        System.out.println();
    }

    /**
     * 打印傳入類的構造器
     * @param c1
     */
    public static void printConstructors(Class c1){
        //1.獲取所有構造器
        Constructor[] constructors=c1.getConstructors();
        //2.遍歷打印
        for(Constructor c:constructors){
            //3.打印tab占位符
            System.out.print("   ");
            //4.獲取構造器的屬性
            String modifier=Modifier.toString(c.getModifiers());
            if(modifier.length()>0)System.out.print(modifier+" ");
            //5.打印構造器名
            String conName=c.getName();
            System.out.print(conName+"(");
            //6.打印參數
            Class[] paraTypes=c.getParameterTypes();
            for(int j=0;j<paraTypes.length;j++){
                if(j>0)System.out.print(", ");
                System.out.print(paraTypes[j].getName());
            }
            System.out.print(");\n");
        }
        System.out.print("\n");
    }

    /**
     * 打印方法
     * @param c1
     */
    public static void printMethods(Class c1){
        //1.獲取所有的方法
        Method[] methods=c1.getMethods();
        //2.遍歷打印
        for(int j=0;j<methods.length;j++){
            //3.打印占位符
            System.out.print("   ");
            //4.打印方法屬性
            String modifiers=Modifier.toString(methods[j].getModifiers());
            if(modifiers.length()>0)System.out.print(modifiers+" ");
            //5.打印返回類型
            String returnType=methods[j].getReturnType().getName();
            System.out.print(returnType+" ");
            //6.打印方法名
            String methodName=methods[j].getName();
            System.out.print(methodName+"(");
            //7.打印參數名
            Class[] paraTypes=methods[j].getParameterTypes();
            for(int i=0;i<paraTypes.length;i++){
                if(i>0)System.out.print(",");
                System.out.print(paraTypes[i].getName());
            }
            if(j+1!=methods.length) System.out.print(")\n");
        }
    }
}

(三)運行時獲取一個對象的數據域的具體值

        Student student=new Student(18);                        //創建student對象
        Class studentClass=student.getClass();                  //獲取Student的Class
        Field field=studentClass.getDeclaredField("age");       //得到age域
        field.setAccessible(true);                              //設置可訪問private域
        System.out.println(field.get(student));                 //訪問age域的值

(四)調用一個對象的方法

        Student student=new Student(18);                                  //創建student對象
        Class studentClass=student.getClass();                          //獲取Student的Class
        Method setAgeMethod=studentClass.getMethod("setAge", int.class);     //獲取方法
        setAgeMethod.invoke(student,20);                               //訪問age域的值
        System.out.println(student.getAge());                            //返回20

(五)實現一個泛型數組操作方法

    /**
     * 用於擴展已經填滿的數組
     * @param a
     * @param newLength
     * @return
     */
    public static Object goodCopyOf(Object a,int newLength){
        Class c1=a.getClass();                          //獲取傳入的a的Class
        if(!c1.isArray())return null;                   //若不是數組類型直接返回null
        Class compomentType=c1.getComponentType();      //獲取數組元素類型
        int length=Array.getLength(a);                  //獲取傳入的數組的長度
        Object newArray=Array.newInstance(compomentType,newLength);                         //Array.newInstance()根據元素類型與長度新建一個相同類型數組且長度擴大              
        System.arraycopy(a,0,newArray,0,Math.min(length,newLength));      //將原數組的值賦予新數組
        return newArray;
    }

參考《Java核心技術 卷I》p190

Java反射總結