反射

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)

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值