0
点赞
收藏
分享

微信扫一扫

Java反射-1(理论)

Java反射-1(理论)
Java反射-2(技巧)
JAVA反射-3(性能)

1. 官网解读:

1.1 什么叫做反射

反射通常是被程序使用,这些程序需要能够检查或修改运行在JVM的应用程序的运行时行为

1.1.1 反射的优点

可扩展功能
应用程序可使用 完全限定的名称 创建 可扩展对象的实例 来使用外部或用户定义的类。

1.1.2 反射的缺点

性能开销
由于反射设计到动态解析的类型,因此无法执行某些JVM的优化。因此,反射操作性能低于非反射操作,应该避免在性能敏感的程序中频繁调用。

内部暴露
由于反射允许代码执行非法的操作在非反射代码中,例如,访问私有字段或方法,因此使用反射可能导致意外的副作用,可能导致代码功能失常并可能失去可移植性,反射代码打破了抽象,因此使用反射的代码可能会在系统升级后表现异常。

安全限制
反射需要运行时的权限,因此无法在安全管理器下运行,必须受限于安全的上下文中运行,例如Applet,只是一个重要的考虑因素。

1.2 Class对象的学习

每一种对象都是引用类型或者基本数据类型。

对于每一种对象的类型,JVM提供了一个不可变对象,java.lang.Class不可变对象提供了检查运行时对象 成员和类型信息的方法。还提供了创建类和对象的功能。最重要的,他是反射API的入口点。

1.2.1 getClass()语法

对象是可用的情况:得到它的class对象最简单的方法就是object.getClass(),当然,这仅仅适用于继承与object下的类。

  public static void main(String[] args) {
        Heap heap = new Heap();
        System.out.println("普通对象的返回类型:" + heap.getClass());
        //注意,声明类型  xx=new 实际类型();返回的是实际类型
        Set set = new HashSet();
        System.out.println("实际类型的返回类型:" + set.getClass());
        //注意数据的返回类型
        byte[] bytes = new byte[1024];
        System.out.println("数组的返回类型:" + bytes.getClass());
        System.out.println("枚举的返回类型:"+enums.RED.getClass());
    }

执行结果:

1.2.2 .class语法

If the type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type.

如果类型可用但没有对象:可以通过Class附带的".class"名称获取Class对象。

1.2.3 Class.forName()语法

If the fully-qualified name of a class is available, it is possible to get the corresponding Class using the static method Class.forName(). This cannot be used for primitive types.

一个类的完全限定名可用:可以使用静态方法Class.forName()去创建Class对象,不能用于基本数据类型。

1.2.4 Type用法

对于基本数据类型.class方式是一种便捷的、首选的方式来获取Class对象。然而有另一种方法去创建Class对象。每一种基本数据类型和void都有一个包装类java.lang。用于将基本数据类型装箱。每一个包装类包含一个TYPE的域,该字段等于Class被包装的基本类型。

对于非基本数据类型,返回的是编译错误。

测试代码:

    public static void main(String[] args) {
        Class dobClass = Double.TYPE;
        //Void也有封装类型!
        Class voidClass=Void.TYPE;
        System.out.println(dobClass);
        System.out.println(voidClass);
    }

输出结果:

1.2.5 返回Class的方法

有几个Reflection API可以返回classes对象,但只有Class对象直接或者间接获取的情况下。
下面getclasses()知识点需要用到成员内部类,可以先了解下。

    public static void main(String[] args) {
        //返回作为类成员的所有公共类,接口和枚举,包括继承的成员。
        Class<?>[] dobClass = HashMap.class.getClasses();
        for (Class c : dobClass) {
            System.out.println("类或其父类所有成员public内部类:" + c);
        }
        Class<?>[] declaredClasses = HashMap.class.getDeclaredClasses();
        for (Class c1 : declaredClasses) {
            System.out.println("本类所有成员内部类:"+c1);
        }
    }

执行结果:

下面这个类实现了:获取类的声明组件,包括修饰符泛型类型参数实现的接口和继承路径。由于 Class实现了java.lang.reflect.AnnotatedElement接口,因此还可以查询运行时注释

public class Reflect {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("Algorithm.Outer");
            out.println("Class:" + c.getCanonicalName());
            out.println("访问修饰符:" + Modifier.toString(c.getModifiers()));
            TypeVariable<? extends Class<?>>[] tv = c.getTypeParameters();
            if (tv.length != 0) {
                for (TypeVariable t : tv) {
                    out.println("泛型类型:" + t.getName());
                }
                out.println();
            } else {
                out.println("--无泛型的参数类型--");
            }
            //获取接口类型
            Type[] intfs = c.getGenericInterfaces();
            if (intfs.length != 0) {
                for (Type intf : intfs)
                    out.println("接口类型:" + intf.toString());
            } else {
                out.format("--无接口类型--");
            }

            //将父类保存到List集合里面
            List<Class> l = new ArrayList<Class>();
            printAncestor(c, l);
            if (l.size() != 0) {
                for (Class<?> cl : l)
                    //打印父类名称
                    out.println("父类名称:" + cl.getCanonicalName());
            } else {
                out.format("--没有父类名称--");
            }
            Annotation[] ann = c.getAnnotations();
            if (ann.length != 0) {
                for (Annotation a : ann)
                    out.println("注释信息:" + a.toString());
            } else {
                out.format(" --没有注释信息--");
            }
            // production code should handle this exception more gracefully
        } catch (ClassNotFoundException x) {
            x.printStackTrace();
        }
    }

    //递归方法,返回所以的父类类型,直至Object类
    private static void printAncestor(Class<?> c, List<Class> l) {
        Class<?> ancestor = c.getSuperclass();
        if (ancestor != null) {
            l.add(ancestor);
            printAncestor(ancestor, l);
        }
    }
}

由于数组是运行时对象,因此所有的类型信息都由JVM定义的。特别是,数组实现Clonablejava.io.Serializable,他的直接超类总是Object

2. 源码实现

/**
     * XML转化为Object
     * 
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public final static void objectFromXml(Object obj, String xml) throws InstantiationException,
            IllegalAccessException {
        Element root = parseXml(xml);
        Class clazz = obj.getClass();
        do
            objectFromXml(obj, clazz, root);
        while ((clazz = clazz.getSuperclass()) != null);
    }

    public final static void objectFromXml(Object obj, Class clazz, Element root)
            throws InstantiationException, IllegalAccessException {
        if (root == null || (root.elements()).size() == 0) {
            return;
        }
        // 获取私有变量
        Field[] fields = clazz.getDeclaredFields();
        // 暴力解除
        Field.setAccessible(fields, true);
        for (Field field : fields) {
            // field.getModififers()获取
            String name = field.getName();
            Class type = field.getType();
            // 内省机制,证明该字段在此对象里面是可编辑的
            if ((!Modifier.isStatic(field.getModifiers())) && PropertyUtils.isWriteable(obj, name)) {
                // 获取属性的类型
                // 判断类型来自哪里(可指定的)
                if (type.isAssignableFrom(List.class)) {
                    // 获取属性的Type类型
                    Type genericType = field.getGenericType();
                    List<Element> elements = root.elements(name);
                    // 根本没有这个节点的话,那么不予赋值
                    if ((elements == null) && elements.size() == 0) {
                        continue;
                    }
                    // 判断该Type类型是不是参数化的文件
                    if (genericType instanceof ParameterizedType) {
                        ParameterizedType pt = (ParameterizedType) genericType;
                        Class parameterizedClass = (Class) pt.getActualTypeArguments()[0];
                        // 想当与new了一个对象
                        List lists = new ArrayList();
                        for (Element ele : elements) {
                            Object object = parameterizedClass.newInstance();
                            // 判断泛型是否是基本数据对象
                            if (isPrimitiveType(parameterizedClass)) {
                                // 将element里面的对象赋值到反射出的对象里面
                                object = setObjectValue(object, ele.getText());
                            } else {
                                // 迭代,无论执行都少次,最后一次,将正确的值返回
                                objectFromXml(object, parameterizedClass, ele);
                            }
                            lists.add(object);
                        }
                        // 将obj对象的List集合赋值
                        field.set(obj, lists);
                    }
                } else {
                    // 若不包含改节点
                    String text = root.elementText(name);
                    if (null != text) {
                        try {
                            if (isPrimitiveType(field.getType())) {
                                setObjectValue(obj, field, text);
                            } else {
                                // 创建改属性的object、class、节点
                                Object fieldObject = type.newInstance();
                                Element fieldRoot = root.element(name);
                                objectFromXml(fieldObject, type, fieldRoot);
                                // 为obj对象里面的field属性赋予fieldObject对象的值
                                field.set(obj, fieldObject);
                            }
                        } catch (NumberFormatException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IllegalArgumentException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (ParseException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

Object转化为XML:

public static void ObjectToXML(Object obj, Element root) throws IllegalArgumentException,
            IllegalAccessException, SecurityException, NoSuchMethodException,
            InvocationTargetException, ParseException {
        // 创建Class对象
        Class clazz = obj.getClass();
        do
            ObjectToXML(obj, clazz, root);
        while ((clazz = clazz.getSuperclass()) != null);
    }

    public static void ObjectToXML(Object obj, Class clazz, Element root)
            throws IllegalArgumentException, IllegalAccessException, SecurityException,
            NoSuchMethodException, InvocationTargetException, ParseException {
        Field[] fields = clazz.getDeclaredFields();
        Field.setAccessible(fields, true);
        for (Field field : fields) {
            // 判断是否是List
            Class fieldClass = field.getType();
            String name = field.getName();
            Object descObj = field.get(obj);
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            if (descObj == null) {
                if (isPrimitiveType(fieldClass)) {
                    descObj = "";
                } else {
                    continue;
                }
            }
            if (fieldClass.isAssignableFrom(List.class)) {
                Type genType = field.getGenericType();
                if (genType instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) genType;
                    Class paramClass = (Class) pt.getActualTypeArguments()[0];
                    System.out.println("List的泛型对象:" + paramClass);
                    String paramText = null;
                    // 判断参数的类型
                    List paramList = (ArrayList) descObj;
                    // foreach循环前需要加判断
                    if (paramList == null || paramList.size() == 0 || paramClass == null) {
                        continue;
                    }
                    Method m = fieldClass.getDeclaredMethod("size", new Class[0]);
                    Integer size = (Integer) m.invoke(descObj, new Object[0]);
                    root.addElement(name + "_NUM").setText(size + "");
                    Element childEle = null;
                    // 获取list集合里面的对象
                    for (Object object : paramList) {
                        if (isPrimitiveType(paramClass)) {
                            childEle = root.addElement(name);
                            root.addText(String.valueOf(getObjectValue(object, paramClass)));
                        } else {
                            childEle = new DOMElement(name);
                            ObjectToXML(object, childEle);
                            root.add(childEle);
                        }
                    }
                }
            } else if (fieldClass.isAssignableFrom(Map.class)) {
                Map map = (Map) descObj;
                Type mapGentype = field.getGenericType();
                // 若是泛型类型
                if (mapGentype instanceof ParameterizedType) {
                    ParameterizedType mapPt = (ParameterizedType) mapGentype;
                    Class keyClass = (Class) mapPt.getActualTypeArguments()[0];
                    Type valueType = mapPt.getActualTypeArguments()[1];
                    Class valueClass = (Class) valueType;
                    Iterator<Map.Entry> it = map.entrySet().iterator();
                    // 默认Key是基本类型
                    while (it.hasNext()) {
                        Entry entry = it.next();
                        Object keyObject = entry.getKey();
                        System.out.println("map的key:" + keyObject);
                        Object valueObject = entry.getValue();
                        System.out.println("map的value:" + valueObject.getClass());
                        Element mapEle = null;
                        // 设置到XML里面
                        String keyName = null;
                        if (isPrimitiveType(keyClass)) {
                            keyName = (String) getObjectValue(keyObject, keyClass);
                        } else {
                            continue;
                        }
                        if (isPrimitiveType(valueClass)) {
                            mapEle = root.addElement(keyName); // 创建节点
                            mapEle.setText((String) getObjectValue(valueObject, valueClass));
                        } else {
                            // 若是对象
                            mapEle = new DOMElement(keyName);
                            Element childEle = null;
                            if (valueObject instanceof List) {
                                // 若是list集合,直接继续赋值
                                List mapList = (ArrayList) valueObject;
                                if (mapList == null || map.size() == 0) {
                                    continue;
                                }
                                Class cls = mapList.get(0).getClass(); // 获取List对象的泛型的对象类型
                                for (Object object : mapList) {
                                    if (isPrimitiveType(cls)) {
                                        childEle = root.addElement(name);
                                        mapEle.addText(String.valueOf(getObjectValue(object, cls)));
                                    } else {
                                        childEle = new DOMElement(name);
                                        ObjectToXML(object, childEle);
                                        mapEle.add(childEle);
                                    }
                                }
                            } else {
                                ObjectToXML(valueObject, mapEle);
                            }
                            root.add(mapEle);
                        }
                    }
                }
            } else {
                // 属性字段是否是普通对象普通对象
                Element childEle = new DOMElement(name);
                if (isPrimitiveType(fieldClass)) {
                    childEle.setText(String.valueOf(getObjectValue(descObj, fieldClass)));
                } else {
                    ObjectToXML(descObj, childEle);
                }
                root.add(childEle);
            }
        }
    }

工具类:

/**
     * 解析Element节点
     * 
     * @param xml
     * @return
     */
    private static Element parseXml(String xml) {
        Element root = null;
        try {
            Document doc = DocumentHelper.parseText(xml);
            root = doc.getRootElement();
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return root;
    }

    /**
     * 
     * @param object
     *            目标对象
     * @param field
     *            目标对象的反射字段
     * @param text
     *            需要反射字段赋予的值
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws NumberFormatException
     * @throws ParseException
     */
    private static void setObjectValue(Object object, Field field, String text)
            throws NumberFormatException, IllegalArgumentException, IllegalAccessException,
            ParseException {
        if (object == null || field == null) {
            return;
        }
        // 获取反射字段的Class对象。getClass()返回的是Field对象
        Class fieldClass = field.getType();
        if (fieldClass.isAssignableFrom(long.class) || fieldClass.isAssignableFrom(Long.class)) {
            field.set(object, Long.valueOf(text));
        } else if (fieldClass.isAssignableFrom(int.class)
                || fieldClass.isAssignableFrom(Integer.class)) {
            field.set(object, Integer.valueOf(text));
        } else if (fieldClass.isAssignableFrom(double.class)
                || fieldClass.isAssignableFrom(Double.class)) {
            field.set(object, Double.valueOf(text));
        } else if (fieldClass.isAssignableFrom(float.class)
                || fieldClass.isAssignableFrom(Float.class)) {
            field.set(object, Float.valueOf(text));
        } else if (fieldClass.isAssignableFrom(boolean.class)
                || fieldClass.isAssignableFrom(Boolean.class)) {
            field.set(object, Boolean.valueOf(text));
        } else if (fieldClass.isAssignableFrom(Date.class)) {
            DateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
            field.set(object, df.parse(text));
        } else if (fieldClass.isAssignableFrom(String.class)) {
            field.set(object, text);
        } else if (fieldClass.isArray()) {
            field.set(object, text.toCharArray());
        } else {
            field.set(object, text);
        }
    }

    private static Object getObjectValue(Object object, Class paramsClass)
            throws IllegalArgumentException, IllegalAccessException, ParseException {
        if (object == null) {
            return null;
        }
        if (paramsClass.isAssignableFrom(Date.class)) {
            DateFormat dt = new SimpleDateFormat("yyyyMMddhhmmss");
            object = dt.format(object);
        } else if (paramsClass.isAssignableFrom(Double.class)
                || paramsClass.isAssignableFrom(double.class)) {
            // double类型格式化
            NumberFormat nf = NumberFormat.getNumberInstance();
            nf.setMaximumFractionDigits(8);
            object = nf.format((Double) object);
        } else {
            object = String.valueOf(object);
        }
        return object;
    }

    // 返回泛型(反射的new)对象的值 。
    private static Object setObjectValue(Object object, String text) {
        if (object == null)
            return null;
        Class clazz = object.getClass();
        if (clazz.isAssignableFrom(long.class) || clazz.isAssignableFrom(Long.class)) {
            object = Long.valueOf(text);
        } else if (clazz.isAssignableFrom(int.class) || clazz.isAssignableFrom(Integer.class)) {
            object = Integer.valueOf(text);
        } else if (clazz.isAssignableFrom(double.class) || clazz.isAssignableFrom(Double.class)) {
            object = Double.valueOf(text);
        } else if (clazz.isAssignableFrom(float.class) || clazz.isAssignableFrom(Float.class)) {
            object = Float.valueOf(text);
        } else if (clazz.isAssignableFrom(boolean.class) || clazz.isAssignableFrom(Boolean.class)) {
            object = Boolean.valueOf(text);
        } else if (clazz.isAssignableFrom(Date.class)) {
            DateFormat df = new SimpleDateFormat("yyyymmddhhmiss");
            try {
                object = df.parse(text);
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            object = text;
        }
        return object;
    }

    // 将其超类删除
    private static boolean isPrimitiveType(Class<?> clazz) {
        boolean isPrimitiveOrPrimitiveClass = Boolean.valueOf(false);
        if ((!clazz.isAssignableFrom(Object.class))
                && ((clazz.isPrimitive() || clazz.isAssignableFrom(Double.class)
                        || clazz.isAssignableFrom(Float.class)
                        || clazz.isAssignableFrom(Long.class)
                        || clazz.isAssignableFrom(Integer.class)
                        || clazz.isAssignableFrom(Boolean.class)
                        || clazz.isAssignableFrom(Byte.class)
                        || clazz.isAssignableFrom(Character.class)
                        || clazz.isAssignableFrom(Short.class)
                        || clazz.isAssignableFrom(String.class) || clazz
                            .isAssignableFrom(Date.class)))) {
            isPrimitiveOrPrimitiveClass = Boolean.valueOf(true);
        }
        return isPrimitiveOrPrimitiveClass;
    }
举报

相关推荐

0 条评论