传智播客 Java网络公开课三内省与注解

来源:互联网 发布:中文编程语言 编辑:程序博客网 时间:2024/05/16 15:26

 

    反射有点难理解,但是张老师的讲解非常通俗,演示的代码虽然精简,但是目的明确,原理很清晰。让人很容易就明白了其中的道理。了解了反射的原理。接下来张老师讲解了在框架中常用的技术——内省机制。内省和反射式相辅相成的,不能单独割裂开来讨论。在前面Java Web视频中,有一章专门讲解了JavaBean。那个时候我们只需要会用就行,至于是怎么实现的是完全不清楚的。如前面提到的JavaBean:一个JavaBean就是其中的方法符合某种命名规则的一个java类。JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。在Java EE开发中,经常要使用到JavaBean,JDK中提供了对JavaBean进行操作的一些API。
    一个JavaBean类可以不当JavaBean用,而当成普通类用。JavaBean实际就是一种规范,当一个类满足这个规范,这个类就能被其它特定的类调用。一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。去掉set前缀,然后取剩余部分,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。下面就用前面的讲解的反射方式来设置或读取JavaBean的属性:
        import java.beans.BeanInfo;
        import java.beans.IntrospectionException;
        import java.beans.Introspector;
        import java.beans.PropertyDescriptor;
    除了反射用到的类需要引入外,内省需要引入的类如上所示,它们都属于java.beans包中的类,自己写程序的时候也不能忘了引入相应的包或者类。下面代码片断是一个设置某个JavaBean类某个属性的关键代码:
        private static void setObjectProperty(ReflectPoint pt1, int value,
                                        String propName) throws IntrospectionException,
                                               IllegalAccessException, InvocationTargetException {
            /*BeanInfo bean = Introspector.getBeanInfo(ReflectPoint.class);
            PropertyDescriptor [] properties = bean.getPropertyDescriptors();
            for(PropertyDescriptor property: properties)
            {
                if(property.getName().equals(propName))
                {
                    Method mSetX = property.getWriteMethod();
                    mSetX.invoke(pt1, value);
                    break;
                }
            }*/
            PropertyDescriptor property = new PropertyDescriptor("x",ReflectPoint.class);
            Method mSetX = property.getWriteMethod();
            mSetX.invoke(pt1, value);
        }
    代码中注释的语句代表一种方式,最后的三行代表另外一种设置相应类相应属性的方式。从简洁上来说,第二种方式显然更优雅。第一种方式中首先是获得相应javaBean的类信息bean,用的BeanInfo这个类来描述的。然后就能够通过getPropertyDescriptors方法获取属性描述数组对象。最后从数组中取去一个个的属性对象进行操作——获取相应的读写方法,然后调用相应的读写方法。这些是通过反射机制做到的。由于这种方式比较麻烦,如果只调用其中一种方法,就要遍历一次属性描述数组,所以就产生了第二种方式,直接通过传入属性名称,相应的javaBean类型参数,构造出一个需要的PropertyDescriptor对象,然后再进行调用。
    理解了相应的原理,那些现成的工具用起来就会更舒服,如Beanutils与PropertyUtils工具。这两个工具设置属性的时候一个主要区别是PropertyUtils.getPropety方法获得的属性值的类型为该属性本来的类型,而BeanUtils.getProperty则是将该属性的值转换成字符串后才返回。
    讲完比较复杂的反射、内省后,接着是还算比较简单的新特性——注解。在编译程序时经常碰到deprecated的问题,而在引入SuppressWarnings注解后,编译器就不再产生刚才的警告。因此,我们需要在代码中加入一些额外的信息来表示某种意义,而注解就为了解决这个问题的。可以看到,当你需要宣布废弃某个方法时,只需要在方法前加上@Deprecated注解,别人在编译用到这个方法的类时就会出现警告信息,同时也加入了不提示警告信息的注解。同样还有一个常用Java本身提供的注解就是@Override,它是用来避免继承时重写某个方法出现方法签名出现错误而达不到重写的目的。可以这么说,加了注解,等于打上了某种标记,没加,则等于没有某种标记,以后,其他程序可以用反射来了解你的类上面有无何种标记,看你有什么标记,就去干相应的事。标记可以加在类,方法,字段,包上,方法的参数上。
    JAVA本身只提供了三种可以使用的注解。如何定义自己的注解?JAVA提供了原注解来定义自定义的注解。首先是@Retention和@Target这两个元注解,它们分别指明自定义注解的作用范围和目标。而取值则是在RetentionPolicy和ElementType中定义。对于范围取值,从字面意思就能理解,分别是RetetionPolicy.SOURCE,RetetionPolicy.CLASS,RetetionPolicy.RUNTIME代表源代码、类、和运行时。

原创粉丝点击