Java基础——反射.

反射是什么?

能够分析类能力的程序称为反射,利用反射能够编写动态操作Java代码的程序

Class类

每个对象都有一个运行时的类型标识,称为Class,用于跟踪对象所属的类

class Person {

}

可通过Object中getClass方法、Class.forName()或T.class获取一个类对应的Class对象,每个java类型都有匹配的类对象

Person person = new Person();
Class personClass = person.getClass();

try {
    Class StringClass = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Class voidClass = Void.class;

其保存了描述类的各种属性,如类名(会附带包名)

String className = personClass.getName()

可通过类对象创建新的实例,newInstance()会调用默认无参的构造方法,无则报错

try {
    Person person2 = (Person) personClass.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
    e.printStackTrace();
}

可通过==运算符判断两个类对象是否相等,多用于equals中

if (person.getClass() == person.getClass()) {

}

利用反射还原类

反射中有Field、Constructor和Method描述类的域、构造方法和方法

  • 都有getName返回名称,Modifier.toString(getMidifiers())获取修饰符
  • Field的getType()获取域的数据类型
  • Constructor和Method的getParameterTypes()获取参数类型
  • getDeclaredFields()、getDeclaredConstructors()、getDeclaredMethods()返回全部域、构造方法和方法(包括private)
  • Method的getReturnType()获取返回值类型
class Reflection {

    public static void reflect(String name) {
        try {
            Class thisClass = Class.forName(name);
            Class supClass = thisClass.getSuperclass();
            String modifies = Modifier.toString(thisClass.getModifiers());
            if (modifies.length() > 0) {
                System.out.print(modifies + " ");
            }
            System.out.print("class " + name);
           if (supClass != null && supClass != Object.class) {
                System.out.print(" extend " + supClass.getName());
            }
            System.out.print(" {\n");
            printField(thisClass);
            System.out.println();
            printConstructors(thisClass);
            System.out.println();
            printMethods(thisClass);
            System.out.println("}");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }

    public static void printField(Class thisClass) {
        Field[] fields = thisClass.getDeclaredFields();
        for (Field f : fields) {
            Class type = f.getType();
            String name = f.getName();
            System.out.print("  ");
            String modifiers = Modifier.toString(f.getModifiers());
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.println(type.getName() + " " + name + ";");
        }
    }


    public static void printConstructors(Class thisClass) {
        Constructor[] constructors = thisClass.getDeclaredConstructors();
        for (Constructor c : constructors) {
            String name = c.getName();
            System.out.print("  ");
            String modifiers = Modifier.toString(c.getModifiers());
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.print(name + "(");
            Class[] paraTypes = c.getParameterTypes();
            for (int i = 0; i < paraTypes.length; i++) {
                if (i > 0) {
                    System.out.println(", ");
                }
                System.out.print(paraTypes[i].getName());
            }
            System.out.println(");");
        }
    }

    public static void printMethods(Class thisClass) {
        Method[] methods = thisClass.getDeclaredMethods();
        for (Method m : methods) {
            Class returnType = m.getReturnType();
            String name = m.getName();
            System.out.print("  ");
            String modifiers = Modifier.toString(m.getModifiers());
            if (modifiers.length() > 0) {
                System.out.print(modifiers + " ");
            }
            System.out.print(returnType.getName() + " " + name + "(");
            Class[] paraTypes = m.getParameterTypes();
            for (int i = 0; i < paraTypes.length; i++) {
                if (i > 0) {
                    System.out.print(", ");
                }
                System.out.print(paraTypes[i].getName());
            }
            System.out.println(");");
        }
    }
}

对于类Person

public class Person {
}

调用时输入类名

Reflection.reflect(Person.class.getName());

输出为

public class com.example.demo0.Person {
  public com.example.demo0.Person();
}

通用toString()

  • getComponentType()获取数组类型
  • setAccessible(AccessibleObject[] array,boolean flag)设置对象数组的可访问标志,true为可访问私有部分
  • Filed的get(Object obj)返回对应域在obj中的值
  • Array的get(obj, i)获取obj数组在i中对象
class ObjectAnalyzer {
    private ArrayList<Object> visited = new ArrayList<>();

    public String toString(Object obj) {
        if (obj == null) {
            return "null";
        }
        if (visited.contains(obj)) {
            return "...";
        }
        visited.add(obj);
        Class thisClass = obj.getClass();
        if (thisClass == String.class) {
            return (String) obj;
        }
        if (thisClass.isArray()) {
            String r = thisClass.getComponentType() + "[]{";
            for (int i = 0; i < Array.getLength(obj); i++) {
                if (i > 0) {
                    r += ",";
                }
                Object val = Array.get(obj, i);
                if (thisClass.getComponentType().isPrimitive()) {
                    r += val;
                } else {
                    r += toString(val);
                }
                return r + "}";
            }
        }
        String r = thisClass.getName();
        do {
            r += "[";
            Field[] fields = thisClass.getDeclaredFields();
            AccessibleObject.setAccessible(fields, true);
            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(obj);
                        if (t.isPrimitive()){
                            r+=val;
                        }else {
                            r+=toString(val);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            r += "]";
            thisClass = thisClass.getSuperclass();
        }
        while (thisClass != null);

        return r;
    }
}

调用

ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    arrayList.add(i * i);
}
System.out.println(new ObjectAnalyzer().toString(arrayList));

通用数组拷贝

现有badCopy利用Object[]进行拷贝

class CopyUtil {

    public static Object[] badCopy(Object[] a, int newLength) {
        Object[] newArray = new Object[newLength];
        System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
        return newArray;
    }
}

以下代码无法执行,在返回时一个Object[]无法转换成Person[],且无法针对基本数据类型转换,因为int[] 无法转换成Object[]

Person[] people = new Person[10];
people = (Person[]) CopyUtil.badCopy(people, 2 % people.length);
//int[] a = new int[10];
//a = CopyUtil.badCopy(a, 2 % a.length);

修改为goodCopy,内部使用反射Array.newInstance创建Object实例,所有对象都可通过Object进行转换

public static Object goodCopy(Object a, int newLength) {
    Class thisClass = a.getClass();
    if (!thisClass.isArray()) {
        return null;
    }
    Class componentType = thisClass.getComponentType();
    int length = Array.getLength(a);
    Object newArray = Array.newInstance(componentType, newLength);
    System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
    return newArray;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值