• 反射笔记


    1. getFields()和getDeclaredFields()的区别

      getFields()和getDeclaredFields()返回Field对象,通过field.getName()获取名称。

      getFields()只能获取声明为public的字段,包括父类的。

      getDeclaredFields()能获取声明的所有字段,包括public,protected,private。

    2. 转载

    关键字:内省、JavaBean、PropertyDescriptor类、Introspector类、BeanUtils工具包、注解、Rentention、Target、注解的基本属性和高级属性
     
    内省IntroSpector
    JavaBean主要用于传递数据信息,其方法用于访问私有变量,且方法名符合某种规则。
        如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。
        内省主要是对JavaBean进行操作。JavaBean内部的方法要按照某种规则命名,例如void setAge(int age)、int getAge()。JavaBean可以作为普通类进行操作;普通类如果内部有set()、get()方法,也可以当做JavaBean使用。
        JavaBean的属性是通过get()和set()方法推断出来的,即去掉get、set后的字母,例如,属性为age,而不是成员变量,因为成员变量看不见。
    获得属性名的规则:如果属性名的第二个字母是小写,则把第一个字母小写。例如,gettime—>time,setTime—>time,getCPU—>CPU。
        JavaBean处理的好处:
        1、JavaEE中许多地方需要使用JavaBean。
        2、JDK给JavaBean提供的API称为内省。
     
        PropertyDescriptor类
        PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
        1、getPropertyType(),获得属性的Class对象。
        2、getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法。
        3、hashCode(),获取对象的哈希值。
        4、setReadMethod(Method readMethod),设置用于读取属性值的方法;setWriteMethod(Method writeMethod),设置用于写入属性值的方法;
        导包java.bean.*;
        通过属性名获取对应的值,利用反射方法,如下:                                         
               ReflectPoint pt1 = new ReflectPoint(7,9);
                  String propertyName = "x";//给一个属性,获取值
                  PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
                  Method methodGetX = pd.getReadMethod();//Read对应get()方法
                  Object reValue = methodGetX.invoke(pt1);
        给某个属性设置值,如下:
               String propertyName2 = "y";//给一个属性,设置值
                  PropertyDescriptor pd2 = new PropertyDescriptor(propertyName2,pt1.getClass());
                  Method methodSetY = pd2.getWriteMethod();//Write对应set()方法
                  methodSetY.invoke(pt1,3);
           右键—》Source—》Generate Geters and Setters,创建get()和set()方法。
        选择一些代码,右键—》Refactor—》Extract Method,创建一个方法,提高复用性。  
     
        Introspector类
        将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。需要导包java.beans.*。
        getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
        private static Object getProperty_2(Object pt1, String propertyName) throws Exception {
                   BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
                   PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
                   Object reValue = null;
                   for(PropertyDescriptor pd : pds){
                         if(pd.getName().equals(propertyName)){
                                Method methodGetX = pd.getReadMethod();
                                reValue = methodGetX.invoke(pt1);
                                break;
                         }
                   }
                   return reValue;
            }
        通过这两个类的比较可以看出,都是需要获得PropertyDescriptor,只是方式不一样:前者通过创建对象直接获得,后者需要遍历,所以使用PropertyDescriptor类更加方便。
       
        BeanUtils工具包              
        为JavaBean提供更多、放方便的功能。
        beanutils.jar = beanutils-core.jar + beanutils-bean-collections.jar,可以通过BuildPath,添加额外的jar包,或者工程下建立lib目录,将jar包复制进来,再加载这个jar包:右键—》add to BuildPath。使用时需要导包:org.apache.commons.beanutils.BeanUtils。
        需要配合使用acpche提供的日志包:logging。
        获得属性的值,例如,BeanUtils.getProperty(pt1,"x"),返回字符串
        设置属性的值,例如,BeanUtils.setProperty(pt1,"y",22),参数是字符串或基本类型自动包装。设置属性的值是字符串,获得的值也是字符串,不是基本类型。
        BeanUtils的特点:
    1、对基本数据类型的属性的操作:在WEB开发、使用中,录入和显示时,值会被转换成字符串,但底层运算用的是基本类型,这些类型转到动作由BeanUtils自动完成。
    2、对引用数据类型的属性的操作:首先在类中必须有对象,不能是null,例如,private Date birthday=new Date();。操作的是对象的属性而不是整个对象,例如,BeanUtils.setProperty(pt1,"birthday.time",121);
    Java7的新特性:Map和JavaBean之间可以进行相互转换,key是属性,value是值。
    describe:JavaBean—>Map;populate:Map—>JavaBean。例如:
        Map map = (name:Kim,age:18);
            BeanUtils.setProperty(map,"name","Kim");
        copyProperties(Object dest, Object orig) ,将一个对象的属性值复制到另一个对象的属性,需要保证属性一致。
       
        PropertyUtils类
        和BeanUtils不同在于,运行getProperty、setProperty操作时,没有类型转换,使用属性的原有类型或者包装类。
     
        注解Annotation
        JDK1.5出现的新特性。在java.lang.annotation包中。
        对于过时的语句,java会提示过时了,通过@SuppressWarnings("Deprecation")在DOS中取消提示,但Eclipse无法取消。这就是注解,相当于标记。编译器、开发工具、javac通过反射获得注解里的内容,进而明确应该做什么、不应该做什么。注解可以加在包、类、属性、方法、参数及局部变量之上。
        一个注解就是一个类。@SuppressWarnings,取消警告。@Deprecated,已过时,老版可以用,新版无法用。
        HashSet集合中,对象必须覆盖Object类的equals()方法,否则会继续使用Object类的equals()方法进行比较,错误的比较方法。覆盖equals()方法,参数必须一致,为了防止错误写入本类的对象,加入@Override,必须正确覆盖父类方法,不是创建新方法。
       
        注解的应用
        在源程序中,调用一个类,这个类会用到注解,需要先准备好注解类,类在调用注解类的对象。注解类的写法类似接口,@interface。先写好注解类A,将注解放在类B中,类C在调用类B时通过反射获得注解类A的内容,进而明确该做什么、不该做什么。可以加上多个注解,加上的实际是注解类的对象:@interfaceA。
        main()方法必须放在一个类下,但与这个类不一定有所属关系。
        在注解类A上加注解B,这个注解B只为这个注解类A服务,B称为“元注解”。类似的还有元信息、元数据。元注解有2个:Rentention和Target。对注解类的注解,可以理解为注解类的属性。
       
     
        Rentention注解类
        注解的生命周期:Java源文件—》class文件—》内存中的字节码。编译或者运行时,都有可能会取消注解。Rentention的3种取值意味让注解保留到哪个阶段,RententionPolicy.SOURCE、RententionPolicy.CLASS(默认值)、RententionPolicy.RUNTIME。
        @Override、@SuppressWarnings是默认保留到SOURCE阶段;@Deprecated是保留到RUNTIME阶段。
        Rentention相当于注解类的一个属性,因为Rentention的值不同,注解类保留到的阶段不同。注解类内部Rentention的值使用value表示,例如,@Deprecated中,value=Runtime。
        Rentention的值是枚举RententionPolicy的值,只有3个:SOURCE、CLASS、RUNTIME。
     
        Target注解类
        性质和Rentention一样,都是注解类的属性,表示注解类应该在什么位置,对那一块的数据有效。例如,@Target(ElementType.METHOD)
    Target内部的值使用枚举ElementType表示,表示的主要位置有:注解、构造方法、属性、局部变量、函数、包、参数和类(默认值)。多个位置使用数组,例如,@Target({ElementType.METHOD,ElementType.TYPE})。
    类、接口、枚举、注解这一类事物用TYPE表示,Class的父类,JDK1.5的新特性。
     
    注解的基本属性
    属性,给注解提供更加详细的信息。
    注解相当于接口,属性相当于方法。例如,@ItcastAnnotation(color="black"),给属性赋值,取值时类似调用方法,例如,System.out.println(annotation.color());。所有的属性必须全部出现,除非有缺省值。
    如果只有value属性,没有其他属性,可以不写=,只针对value,例如,@SuppressWarnings("Deprecation")。或者有其他属性而且有缺省值,例如,String color() default "blue";,此时value单独出现,不用=。
    获得注解的属性的值,例如
    if(AnnotationDemo.class.isAnnotationPresent(ItcastAnnotation.class)){
            ItcastAnnotation annotation =
                  (ItcastAnnotation)AnnotationDemo.class.getAnnotation(ItcastAnnotation.class);
            System.out.println(annotation.color());
            }
    }
    利用反射获得注解的对象,在让该对象调用属性对应的方法。注意类型转换。
    Rentention和Target也是属性,都是value对应的值,值的类型分别是RententionPolicy和ElementType,例如,@Retention(value=RetentionPolicy.RUNTIME)。
     
    注解的高级属性
    给注解增加高级属性,数组、枚举、注解。
    数组类型的属性
    例如,int[] arr() default {3,7,5};,MyAnnotation(arr={3,7,6})。如果数组只有1个元素,可以不加{}。@Target({ElementType.METHOD,ElementType.TYPE})也是数组类型的属性。
    枚举类型的属性
    //注解类内部的内容
    EnumerationDemo.TrafficLamp lamp() default EnumerationDemo.TrafficLamp.RED;
    //调用注解的类上
    @ItcastAnnotation(lamp=EnumerationDemo.TrafficLamp.YELLOW)
    //对注解进行操作
    System.out.println(annotation.lamp().nextLamp().name());
    注解类型的属性
    将一个注解类作为属性加入到另一个注解类中。
    MetaAnnotation annotationAtt() default @MetaAnnotation("Jobs")
    @ItcastAnnotation(annotationAtt=@MetaAnnotation("Kim"))
    annotation.annotationAtt().value()
    注解的返回值可以是8个基本类型、String、Class、枚举以及前面类型的数组,内部还有属性。
    需要详细学习注解,可以通过java语言规范,即languagespecification。
    

    3.getter()和setter()方法

    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    /**
     * 返回Json字符串
     * Created by YuChaofan on 2016/9/8.
     */
    public class ReturnString {
    
        // 主要方法
        private String make(List<?> list) {
            StringBuilder jsonString = new StringBuilder();
            jsonString.append("[");
    
            if(list != null && list.size() > 0) {
                // 获得键与方法名称
                Object[][] keysAndMethods = obtainAllKeysAndMethods(list);
    
                // 拼接字符串
                if(keysAndMethods.length > 0) {
                    for(Object obj : list) {
                        jsonString.append("{");
    
                        for(Object[] kam : keysAndMethods) {
                            String key = (String) kam[0];
                            jsonString.append(""");
                            jsonString.append(key);
                            jsonString.append(""");
                            jsonString.append(":");
                            String getterMethod = (String)kam[1];
                            try {
                                Method method = obj.getClass().getMethod(getterMethod);
                                Object o = method.invoke(obj);
                                if(o instanceof Number || o instanceof Boolean) { // 如果是数字
                                    jsonString.append(o);
                                } else {
                                    jsonString.append(""");
                                    jsonString.append(o);
                                    jsonString.append(""");
                                }
    
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            jsonString.append(",");
                        }
                        jsonString.deleteCharAt(jsonString.length()-1);
                        jsonString.append("},");
                    }
                    jsonString.deleteCharAt(jsonString.length()-1);
                }
    
            }
            jsonString.append("]");
            return jsonString.toString();
        }
    
        private Object[][] obtainAllKeysAndMethods(List<?> list) {
            Object obj = list.get(0);
            Class cls = obj.getClass();
            Field[] fds = cls.getDeclaredFields();
            Object[][] keysAndMethods = new String[fds.length][2];
            for(int i=0; i<fds.length; i++) {
                keysAndMethods[i][0] = fds[i].getName();
                keysAndMethods[i][1] = gainGetterMethodsName((String) keysAndMethods[i][0], fds[i].getType());
            }
            return keysAndMethods;
        }
    
        private String gainGetterMethodsName(String key, Object type) {
            String method = "get";
            if(type.toString().equals("boolean")) {
                method = "is";
            }
            if(!Character.isUpperCase(key.charAt(0))) {
                method += key.substring(0, 1).toUpperCase() + key.substring(1);
            } else {
                method += key;
            }
            return method;
        }
    
        public static void main(String[] args) {
            List<BeanForReflect> list = new ArrayList<>();
            BeanForReflect zha = new BeanForReflect(1, 1, (short) 1, 1, (byte) 1, true, (char) 1, (float) 1, "1xx1", new Date(), null);
            list.add(new BeanForReflect(1, 1, (short) 1, 1, (byte) 1, true, (char) 1, (float) 1, "1xx1", new Date(), zha));
            list.add(new BeanForReflect(2, 2, (short) 2, 2, (byte) 2, false, (char) 2, (float) 2, "2xx2", new Date(), zha));
            list.add(new BeanForReflect(3, 3, (short) 3, 3, (byte) 3, true, (char) 3, (float) 3, "3xx3", new Date(), zha));
            ReturnString ttr = new ReturnString();
            String jsy = ttr.make(list);
    
            System.out.println(jsy);
        }
    
    }
    

    4.PropertyDescriptor()方法

    import java.beans.IntrospectionException;
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    /**
     * 返回Json字符串
     * Created by YuChaofan on 2016/9/8.
     */
    public class WriteMethod {
    
        // 主要方法
        private String make(List<?> list) {
            StringBuilder jsonString = new StringBuilder();
            jsonString.append("[");
    
            if(list != null && list.size() > 0) {
                // 获得键与方法名称
                Object obj = list.get(0);
                Class cls = obj.getClass();
                Field[] fds = cls.getDeclaredFields();
                for(int i=0; i<fds.length; i++) {
                    String key = fds[i].getName();
                    // 问题是getter、setter方法必须完整
                    PropertyDescriptor pd = null;
                    try {
                        pd = new PropertyDescriptor(key, cls);
                    } catch (IntrospectionException e) {
                        e.printStackTrace();
                    }
    
                    Method getterMethod = pd.getReadMethod();
    
                    jsonString.append("{");
                    jsonString.append(""");
                    jsonString.append(key);
                    jsonString.append(""");
                    jsonString.append(":");
                    try {
                        Object o = getterMethod.invoke(obj);
                        if(o instanceof Number || o instanceof Boolean) { // 如果是数字
                            jsonString.append(o);
                        } else {
                            jsonString.append(""");
                            jsonString.append(o);
                            jsonString.append(""");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    jsonString.append(",");
                }
                jsonString.deleteCharAt(jsonString.length()-1);
                jsonString.append("},");
    
            }
    
            jsonString.append("]");
            return jsonString.toString();
        }
    
        public static void main(String[] args) {
            List<BeanForReflect> list = new ArrayList<>();
            BeanForReflect zha = new BeanForReflect(1, 1, (short) 1, 1, (byte) 1, true, (char) 1, (float) 1, "1xx1", new Date(), null);
            list.add(new BeanForReflect(1, 1, (short) 1, 1, (byte) 1, true, (char) 1, (float) 1, "1xx1", new Date(), zha));
            list.add(new BeanForReflect(2, 2, (short) 2, 2, (byte) 2, false, (char) 2, (float) 2, "2xx2", new Date(), zha));
            list.add(new BeanForReflect(3, 3, (short) 3, 3, (byte) 3, true, (char) 3, (float) 3, "3xx3", new Date(), zha));
            WriteMethod ttr = new WriteMethod();
            String jsy = ttr.make(list);
    
            System.out.println(jsy);
        }
    
    }
    

      

  • 相关阅读:
    名师破解英语四级汉译英
    名师破解英语四级汉译英
    名师破解英语四级汉译英
    输出矩阵右上角元素
    输入行列式中偶数行和偶数列的数据
    转秩矩阵
    数据排序
    从键盘上输入5个数,输出最大、最小元素的值以及它们的下标
    中文处理(全角/半角)
    获取汉字拼音首字母
  • 原文地址:https://www.cnblogs.com/loveflycforever/p/5891207.html
Copyright © 2020-2023  润新知