反射笔记

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([email protected]("Kim"))
annotation.annotationAtt().value()
注解的返回值可以是8个基本类型、String、Class、枚举以及前面类型的数组,内部还有属性。
需要详细学习注解,可以通过java语言规范,即languagespecification。

  

时间: 2024-10-10 09:28:44

反射笔记的相关文章

反射 笔记

<1> 定义:Java程序中的各个java类属于同一类事物,描述这类事物的java类就是Class <2> 对比提问:众多的人用一个什么类表示?众多的java类用一个什么类表示? 人   Person Java类     Class <3>  对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类对象java类,它的各个实例对象又分别对应什么呢? >对应各个类在内存中的字节码,例如.Person类的字节码,ArrayList类的

python 反射笔记

反射:是指以字符串的形式传入要执行的对象或者要获取的信息 以下以代码的执行步骤来演示:创建一个包:test:   --__init__   --fanshe.py   --main.py fanshe.py GB = '这是全局变量'   def func1():     return '这是反射函数func1的结果' def func2():     return '这是反射函数func2的结果' def func3():     return '这是反射函数func3的结果' main.py

C#基础系列:反射笔记

前言:使用反射也有几年了,但是一直觉得,反这个概念很抽象,今天有时间就来总结下这个知识点. 1.为什么需要反射: 最初使用反射的时候,作为小菜总是不理解,既然可以通过new 一个对象的方式得到对象,然后通过对象去调用属性和方法,那么为什么还需要反射去调用呢?后来使用多了发现这就是一个先绑定还是后绑定的问题,很多初使用反射的开发人员通常都会有类似这种疑虑:既然在开发时就能够写好代码,干嘛还放到运行期去做,不光繁琐,而且效率也受影响.博主觉得主要是适用性的问题,如果你的系统没有那么高的扩展性和灵活性

C#基础系列——反射笔记

前言:使用反射也有几年了,但是一直觉得,反这个概念很抽象,今天有时间就来总结下这个知识点. 1.为什么需要反射: 最初使用反射的时候,作为小菜总是不理解,既然可以通过new 一个对象的方式得到对象,然后通过对象去调用属性和方法,那么为什么还需要反射去调用呢?后来使用多了发现这就是一个先绑定还是后绑定的问题,很多初使用反射的开发人员通常都会有类似这种疑虑:既然在开发时就能够写好代码,干嘛还放到运行期去做,不光繁琐,而且效率也受影响.博主觉得主要是适用性的问题,如果你的系统没有那么高的扩展性和灵活性

反射笔记(转载)

Java反射机制详解 java 反射 定义 功能 示例 概要: Java反射机制详解 | |目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详见下例 ·通过反射机制实例化一个类的对象 ·获取某个类的全部属性 ·获取某个类的全部方法 ·通过反射机制调用某个类的方法 ·通过反射机制操作某个类的属性 ·反射机制的动态代理 4反射机制的应用实例 ·在泛型为

C#基础系列——再也不用担心面试官问我“事件”了

前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类...你是否也曾经被问到过?你又是否都答出来了呢?上两篇由浅及深介绍了下委托的用法,这篇还是来说说事件.希望通过这篇的介绍,博友能有个系统的认识,至少应付面试没问题了吧.不信?瞧瞧去~~ C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序列化效率比拼 C#基础系列——反射笔记 C

C#基础系列——Attribute特性使用

前言:上篇 C#基础系列--反射笔记 总结了下反射得基础用法,这章我们来看看C#的另一个基础技术--特性. 1.什么是特性:就博主的理解,特性就是在类的类名称.属性.方法等上面加一个标记,使这些类.属性.方法等具有某些统一的特征,从而达到某些特殊的需要.比如:方法的异常捕捉,你是否还在某些可能出现异常的地方(例如数据库的操作.文件的操作等)经常使用try...catch.这个时候如果使用特性,就可以大大减少方法里面的try...catch的使用.你只需要定义一个专门捕捉异常的特性类Excepti

C#基础系列——一场风花雪月的邂逅:接口和抽象类

前言:最近一个认识的朋友准备转行做编程,看他自己边看视频边学习,挺有干劲的.那天他问我接口和抽象类这两个东西,他说,既然它们如此相像, 我用抽象类就能解决的问题,又整个接口出来干嘛,这不是误导初学者吗.博主呵呵一笑,回想当初的自己,不也有此种疑惑么...今天打算针对他的问题,结合一个实际的使用场景来说明下抽象类和接口的异同,到底哪些情况需要用接口?又有哪些情况需要用抽象类呢? C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序

C#基础系列——小话泛型

前言:前面两章介绍了C#的两个常用技术:C#基础系列——反射笔记 和 C#基础系列——Attribute特性使用 .这一章来总结下C#泛型技术的使用.据博主的使用经历,觉得泛型也是为了重用而生的,并且大部分时候会和反射一起使用.这次还是打算围绕WWH(即What.Why.How)来讲解. 1.什么是泛型:通过参数化类型来实现在同一份代码上操作多种数据类型.利用“参数化类型”将类型抽象化,从而实现灵活的复用.怎么理解呢,其实根据博主的理解,泛型就是将类型抽象化,使用抽象化的类型或对象去实现某些功能