反射

https://www.cnblogs.com/yrstudy/p/6500982.html 反射的好處

反射
這裏寫圖片描述

Class
這裏寫圖片描述

public class ReflectionTest {

    public static void main(String[] args) {
        String name;
        if(args.length > 0) name = args[0];
        else
        {
            Scanner in = new Scanner(System.in);
            System.out.println("Enter class name (e.g java.util.Date):");
            name = in.next();
        }

        try
        {
            Class c1 = Class.forName(name);
            Class superC1 = c1.getSuperclass(); //返回父類
            String modifiers = Modifier.toString(c1.getModifiers());//Modifier修飾符工具類
            if(modifiers.length() > 0) System.out.print(modifiers + " ");
            System.out.print("class " + name);
            if(superC1 != null && superC1 != Object.class) System.out.print(" extends "
                    + superC1.getName());
            System.out.print("\n{\n");

            printFields(c1);
            System.out.println();
            printConstructors(c1);
            System.out.println();
            printMethods(c1);
            System.out.println("}");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void printFields(Class c1) {
        //返回 Field 對象的一個數組,這些對象反映此 Class 對象所表示的類或接口所聲明的所有字段。
        Field[] fields = c1.getDeclaredFields();
        for(Field f : fields) {
            System.out.print("  ");
            String modifiers = Modifier.toString(f.getModifiers()); //修飾符
            Class type = f.getType(); //變量類型
            String name = f.getName(); //變量名
            if(modifiers.length() > 0) System.out.print(modifiers + " ");
            System.out.println(type.getSimpleName() + " " + name + ";");
        }
    }

    public static void printConstructors(Class c1) {
        //返回一個 Constructor 對象,該對象反映此 Class 對象所表示的類或接口的指定構造方法。
        Constructor[] constructors = c1.getDeclaredConstructors();
        for(Constructor c : constructors) {
            System.out.print("  ");
            String modifiers = Modifier.toString(c.getModifiers()); //修飾符
            String name = c.getName(); //方法名
            if(modifiers.length() > 0) System.out.print(modifiers + " ");
            System.out.print(name + "(");

            Class[] paramTypes = c.getParameterTypes(); //顯示參數
            for(int j = 0; j < paramTypes.length ; j++) {
                if(j > 0) System.out.print(", ");
                System.out.print(paramTypes[j].getSimpleName());
            }
            System.out.println(");");
        }
    }

    public static void printMethods(Class c1) {
        //返回 Method 對象的一個數組,這些對象反映此 Class 對象表示的類或接口聲明的所有方法,
        //包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。
        Method[] methods = c1.getDeclaredMethods();
        for(Method m : methods)
        {
            System.out.print("  ");
            String modifiers = Modifier.toString(m.getModifiers()); //修飾符
            Class retType = m.getReturnType(); //返回值
            String name = m.getName(); //方法名
            if(modifiers.length() > 0) System.out.print(modifiers + " ");
            System.out.print(retType.getSimpleName() + " " + name + "(");

            Class[] paramTypes = m.getParameterTypes(); //顯示參數
            for(int j = 0; j < paramTypes.length; j++) {
                System.out.print(paramTypes[j].getSimpleName());
                if(j > 0 ) System.out.print(", ");
            }
            System.out.println(");");
        }
    }
}

結果:

Enter class name (e.g java.util.Date):
java.lang.String
public final class java.lang.String
{
  private final char[] value;
  private int hash;
  private static final long serialVersionUID;
  private static final ObjectStreamField[] serialPersistentFields;
  public static final Comparator CASE_INSENSITIVE_ORDER;

  public java.lang.String(byte[], int, int);
  public java.lang.String(byte[], Charset);
  public java.lang.String(byte[], String);
  public java.lang.String(byte[], int, int, Charset);
  public java.lang.String(byte[], int, int, String);
  java.lang.String(char[], boolean);
    .
    .
    .

  public boolean equals(Object);
  public String toString();
  public int hashCode();
  public int compareTo(String);
  public volatile int compareTo(Object);
  public int indexOf(Stringint, );
  public int indexOf(String);
    .
    .
    .
}

查看任意對象的內部信息

public class ObjectAnalyzer {

    /**
     * 標記是否被訪問過 
     */
    private ArrayList<Object> visited = new ArrayList<>();

    public String toString(Object object) {
        // 如果爲null,就返回一個null字符串
        if(object == null) return "null";
        // 記錄該對象是否被訪問過  
        if(visited.contains(object)) return "...";
        // 標記該對象被訪問
        visited.add(object);
        // 獲取class實例
        Class c1 = object.getClass();
        // 如果是String的類直接返回String
        if(c1 == String.class) return (String) object;
        // 如果是一個數組類型
        if(c1.isArray()) {
            // 獲取該數組的數據類型 -> 開始數組
            String r = c1.getComponentType() + "[]{";
            // 遍歷該數組
            for(int i = 0; i < Array.getLength(object); i++) {
                // 如果不是第一個需要輸入,(方便查看)
                if(i>0) r += ",";
                //  返回指定數組對象中索引組件的值。
                Object val = Array.get(object, i);
                // 判斷數組是否爲基本類型,如果不是基本類型還要繼續遍歷(遞歸)
                if(c1.getComponentType().isPrimitive()) {
                    // 如果是基本類型就添加字符串
                    r += val;
                } else {
                    // 遞歸(使用 += 繼續拼接字符串)
                    r += toString(val);
                }
            }
            // ->閉合數組字符串
            return r+"}";
        }

        // 如果不是數組
        // 獲取類的名稱
        String r = c1.getName();
        do {
            // 開始拼接字符串
            r += "[";
            // 獲取所有的實例域
            Field[] fields = c1.getDeclaredFields();
            // 設置所有的實例域都可以訪問(由於有的類中的屬性字段爲private的類型) 
            AccessibleObject.setAccessible(fields, true);
            // 遍歷field
            for(Field f : fields) {
                // 判斷如果是非靜態的屬性
                if(!Modifier.isStatic(f.getModifiers())) {
                    //如果開頭不是 "[" 使用,號隔開,目的是方便查看
                    if(!r.endsWith("[")) r += ",";
                    //獲取名稱,並拼接字符串
                    r += f.getName() + "=";
                    try {
                        // 獲取屬性的數據類型
                        Class t = f.getType();
                        // 獲取該屬性的數據值
                        Object val = f.get(object);
                        // 判斷是否爲基本類型,如果是就拼接,如果不是就再次遞歸
                        if(t.isPrimitive()) r += val;
                        else r += toString(val);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                } 

            }

            //結束標記
            r += "]";
            // 獲取到超類,一直向上遍歷
            c1 = c1.getSuperclass();
        }while(c1 != null);
        // 返回最終的字符串
        return r;
    }
}

結果:

java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],null,null,null,null,null,null,null},size=3][modCount=3][][]
java.lang.reflect.Array

public static Object get(Object array,int index)
返回指定數組對象中索引組件的值。
array - 數組
index - 索引 

public static int getLength(Object array)
以 int 形式返回指定數組對象的長度。 
array - 數組 
java.lang.Class<T>

public T newInstance()
創建此 Class 對象所表示的類的一個新實例。

public boolean isPrimitive()
判定指定的 Class 對象是否表示一個基本類型。

public boolean isArray()
判定此 Class 對象是否表示一個數組類。

public Class<?> getComponentType()
返回表示數組組件類型的 Class
java.lang.reflect.Field

public Object get(Object obj)
返回指定對象上此 Field 表示的字段的值。

public void set(Object obj, Object value)
將指定對象變量上此 Field 對象表示的字段設置爲指定的新值。
java.lang.reflect.AccessibleObject

public boolean isAccessible()
獲取此對象的 accessible 標誌的值。 

public void setAccessible(boolean flag)
將此對象的 accessible 標誌設置爲指示的布爾值。

public static void setAccessible(AccessibleObject[] array, boolean flag)
使用單一安全性檢查(爲了提高效率)爲一組對象設置 accessible 標誌的便捷方法。

使用反射編寫泛型數組代碼擴展數組長度

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        String[] a = {"Hello","World","Good"};
        a = Arrays.copyOf(a, 10);
        System.out.println(Arrays.toString(a));

        String[] b = {"Tom", "Dick", "Harry"};
        b = (String[]) goodCopyOf(b, 10);
        System.out.println(Arrays.toString(b));

        String[] c = {"Tom", "Dick", "Harry"};
        // String[]數組轉換爲Object
        Object obj = c;
        // 再從Object轉換爲String[]數組都是可以的
        c = (String[]) obj;
        // java.lang.ClassCastException
        // 返回的是新建的Object[]數組,這個新建的Object[]數組無法轉換爲String[]數組
        c = (String[]) badCopyOf(c, 10);

    }

    public static Object[] badCopyOf(Object[] a,int newLength) {
        // newArray一開始就是Object[]數組
        Object[] newArray = new Object[newLength];
        System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
        return newArray; //這是返回的是newArray
    }

    public static Object goodCopyOf(Object a, int newLength) {
        Class c1 = a.getClass();
        if(!c1.isArray()) return null;
        Class componentType = c1.getComponentType();
        int length = Array.getLength(a);
        Object newArray = Array.newInstance(componentType, newLength);
        System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
        return newArray;
    }

}

結果:

[Hello, World, Good, null, null, null, null, null, null, null]
[Tom, Dick, Harry, null, null, null, null, null, null, null]
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
    at com.reflection3.Test.main(Test.java:30)

這裏寫圖片描述

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