反射

来源:互联网 发布:手机淘宝优惠券在哪里 编辑:程序博客网 时间:2024/05/01 11:58

(一)Java类

Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值。

Java程序中的各个Java类,它们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?

这个类的名字就是Class

类的名字,类的访问属性,类所属于的包名,字段名称的列表、方法名称的列表,等等。学习反射,首先就要明白Class这个类。

 

(二)如何得到各个字节码对应的实例对象Class类型)
1、类名.class
例如,System.class
           Class  cls1=Date.class//字节码1
2、对象.getClass()
例如,new Date().getClass()
            Person p1=new Person();
            p1.getClass();
3、Class.forName("类名"):静态方法,去查询或加载字符串所对应的类的字节码
作用:返回字节码,方式有两种
             1)以前被加载过,已经在java虚拟机里面了,直接返回
             2) 在java虚拟机里面还没有字节码,则用类加载器去加载,把加载进来的字节码放在虚拟机里面,
例如,Class.forName("java.util.Date");

 

(三)九个预定义Class实例对象:
    八个基本数据类型加一个void.class();
    boolean,byte,char,short,int,long,floor,double
1、包装类型基本类型字节码:TYPE
Int.class == Integer.TYPE

2、数组类型的Class实例对象:

Class.isArray()

 

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[]void…
eg:
String str1="abc";Class cls1=str1.getClass();Class cls2=String.class;Class cls3=Class.forName("java.lang.String");//这三个字节码在内存中对应的是同一个System.out.println(cls1==cls2);System.out.println(cls1==cls3);System.out.println(cls1.isPrimitive());//isPrimitive是否是原始类型System.out.println(cls1);System.out.println(int.class.isPrimitive());System.out.println(int.class==Integer.class);System.out.println(int.class==Integer.TYPE);//TYPE代表包装类型包装的基本类型字节码System.out.println(int[].class.isPrimitive());System.out.println(int[].class.isArray());


 
(四)反射就是把Java类中的各种成分映射成相应的java类。

表示java类的Class类提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,

这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等

(1)Constructor类

Constructor代表某个类中的一个构造方法
1、得到某个类所有的构造方法:
例子:Constructor [] constructors=Class.forName("java.lang.String").getConstructors();
2、得到某一个构造方法
  例子:       Constructor constructor =Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);

  //获得方法时要用到类型

3、创建实例对象:
   通常方式:Stringstr = new String(newStringBuffer("abc"));
   反射方式: String str = (String)constructor.newInstance(newStringBuffer("abc"));

  //调用获得的方法时要用到上面相同类型的实例对象

//new String(new StringBuffer("abc"));Constructor constructor1=String.class.getConstructor(StringBuffer.class);/*JDK1.5的一个新特性:getConstructor里面可以指定若干个class对象,每一个class对象代表一个类型StringBuffer表示选择哪个构造方法String类的字节码  指定内容编译,翻译成class*/String str2=(String)constructor1.newInstance(new StringBuffer("abc"));//拿String类字节码构造的对象//实例化//StringBuffer表示用上边这个构造方法时还要传进一个StringBuffer对象进去System.out.println(str2.charAt(2));

4、Class.newInstance()方法:不带参数
   例子:Stringobj = (String)Class.forName("java.lang.String").newInstance();
   该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

   该方法内部用到了缓存机制来保存默认构造方法的实例对象。

 路径:D:\Program Files\Java\jdk1.6.0_10下 src.zip文件 打开src.zip\java\lang  Class.java   找到newInstance0



(2)Field代表某个类中的一个成员变量
       产生构造方法:
        在ReflectPoint.java中
        快捷键:Alt+Shift+S  选择Generate Constructor using Fields...
        不能用快捷键时:用eclipse自动生成Java类的构造方法(右键->Sourse->Generate Constructor using Fields... )

public class ReflectPoint {private int x;public int y;public ReflectPoint(int x, int y) {super();this.x = x;this.y = y;}}

import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;public class ReflectTest {/** * @param args * @throws ClassNotFoundException  * @throws NoSuchMethodException  * @throws SecurityException  * @throws InvocationTargetException  * @throws IllegalAccessException  * @throws InstantiationException  * @throws IllegalArgumentException  * @throws NoSuchFieldException  */public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {// TODO Auto-generated method stubReflectPoint pt1=new ReflectPoint(3,5);Field fieldY=pt1.getClass().getField("y");//字节码可以getField,getField只能得到可见的//fildY的值是多少?fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值System.out.println(fieldY.get(pt1));Field fieldX=pt1.getClass().getDeclaredField("x");//x不可见所以要用getDeclaredFieldfieldX.setAccessible(true);//暴力反射,设置成可以访问,没有这一步fieldX.get(pt1)通不过System.out.println(fieldX.get(pt1));}}

import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;public class ReflectTest {/** * @param args * @throws ClassNotFoundException  * @throws NoSuchMethodException  * @throws SecurityException  * @throws InvocationTargetException  * @throws IllegalAccessException  * @throws InstantiationException  * @throws IllegalArgumentException  * @throws NoSuchFieldException  */public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {// TODO Auto-generated method stubString str1="abc";Class cls1=str1.getClass();Class cls2=String.class;Class cls3=Class.forName("java.lang.String");System.out.println(cls1==cls2);System.out.println(cls1==cls3);System.out.println(cls1.isPrimitive());System.out.println(cls1);System.out.println(int.class.isPrimitive());System.out.println(int.class==Integer.class);System.out.println(int.class==Integer.TYPE);System.out.println(int[].class.isPrimitive());System.out.println(int[].class.isArray());//new String(new StringBuffer("abc"));Constructor constructor1=String.class.getConstructor(StringBuffer.class);String str2=(String)constructor1.newInstance(new StringBuffer("abc"));System.out.println(str2.charAt(2));ReflectPoint pt1=new ReflectPoint(3,5);Field fieldY=pt1.getClass().getField("y");//getField只能得到可见的//fildY的值是多少?fieldY不是对象身上的变量,要用它去取某个对象上对应的值System.out.println(fieldY.get(pt1));Field fieldX=pt1.getClass().getDeclaredField("x");fieldX.setAccessible(true);//暴力反射,设置成可以访问System.out.println(fieldX.get(pt1));}}

 

 

 

eg:

import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;public class ReflectTest {/** * @param args * @throws Exception  */public static void main(String[] args) throws Exception {changeStringValue(pt1);System.out.println(pt1);}private static void changeStringValue(Object obj) throws Exception{// TODO Auto-generated method stubField[] fields=obj.getClass().getFields();for(Field field: fields){//if(field.getType().equals(String.class)) 因为是string类型,所以==比较好if(field.getType()==String.class){String oldValue=(String)field.get(obj);String newValue=oldValue.replace('b', 'a');field.set(obj, newValue);}}}}


 

 

public class ReflectPoint {public String str1="ball";public String str2="basketball";public String str3="itcast";@Overridepublic String toString(){return str1+":"+str2+":"+str3;}}


 

(3)Method代表某个中的一个成员方法
1、得到类中的某一个方法:
例子:       Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
 
2、调用方法:
通常方式str.charAt(1);
反射方式charAt.invoke(str, 1);
 
如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法

3、jdk1.4jdk1.5invoke方法的区别:
Jdk1.5public Object invoke(Objectobj,Object...args)   用可变参数
Jdk1.4public Object invoke(Objectobj,Object[]args)
            jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,
             所以,调用charAt方法的代码也可以用Jdk1.4改写为charAt.invoke(“str”, new Object[]{1})形式。
 
                String str1="abc";               
                Method methodCharAt=String.class.getMethod("charAt", int.class);System.out.println(methodCharAt.invoke(str1, 1));//jdk1.4System.out.println(methodCharAt.invoke(str1,new Object[]{2}));

 
(五)用反射方式执行某个类中的main方法

      根据用户提供的类名,去执行该类中的main方法

1、用静态代码的方法调用main方法:

public class ReflectTest {/** * @param args * @throws Exception  */public static void main(String[] args) throws Exception {          TestArguments.main(new String[]{"111","222","333"});}class TestArguments{public static void main(String[] args){for(String arg : args){System.out.println(arg);}}}

2、用反射执行


按F2,会出现完整包名

右键->run as ->open configurations...(打开运行对话框)

main标签指运行的那个类,Arguments指要传递的参数,例子中要传的参数是:cn.itcast.day1.TestArguments

相当于在运行里执行:java ReflectTest cn.itcast.day1.TestArguments (注:把cn.itcast.day1.TestArguments这个字符串传给了类ReflectTest)

 

用反射执行的原因

启动Java程序的main方法的参数是一个字符串数组,

public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?

jdk1.5的语法,整个数组是一个参数,

而按jdk1.4的语法,数组中的每个元素对应一个参数,

当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?

jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。

所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”})javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题

eg:

                String startingClassname=args[0];Method mainMethod=Class.forName(startingClassname).getMethod("main",String[].class);//mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});//把整个数组装成一个包mainMethod.invoke(null, (Object)new String[]{"111","222","333"});


(六)数组的反射

1、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
3、基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;
       非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
4、Arrays.asList()方法处理int[]String[]时的差异。
5、Array工具类用于完成对数组的反射操作。
/*              int[] a1=new int[3];int[] a2=new int[4];int[][] a3=new int[2][3];String[] a4=new String[4]*/;int[] a1=new int[]{1,2,3};int[] a2=new int[4];int[][] a3=new int[2][3];String[] a4=new String[]{"a","b","c"};System.out.println(a1.getClass() == a2.getClass());//System.out.println(a1.getClass() == a4.getClass());//System.out.println(a1.getClass() == a3.getClass());System.out.println(a1.getClass().getName());//结果[I  :[代表数组;I代表int类型System.out.println(a1.getClass().getSuperclass().getName());//获取父类  结果: java.lang.ObjectSystem.out.println(a4.getClass().getSuperclass().getName());Object aObj1=a1;Object aObj2=a4;//Object[] aObj3=a1;//数组里装的是int类型的,不是Object类型的,a1是基本数据类型int的,不是ObjectObject[] aObj4=a3;//Object数组里装的是一维数组Object[] aObj5=a4;System.out.println(a1);//[I@1f33675   int类型的[数组的哈希code值1f33675System.out.println(a4);//[Ljava.lang.String;@7c6768System.out.println(Arrays.asList(a1));//1.4 asList(Object[] a);1.5asList(T...a)当成一个objectSystem.out.println(Arrays.asList(a4));


 

 

public static void main(String[] args) throws Exception {                printObject(a4);printObject("xyz");}private static void printObject(Object obj) {// TODO Auto-generated method stubClass clazz=obj.getClass();if(clazz.isArray()){int len=Array.getLength(obj);for(int i=0;i<len;i++){System.out.println(Array.get(obj,i));}}else{System.out.println(obj);}}


(六)反射的作用(实现框架的功能)

使用类时:一种是你调用别人的类,一种是别人调用你的类,这两种类一个叫框架,一个叫工具

                  eg:我去买房子,用的是开发商提供的房子,做门的时候用别人做的锁,两个东西用法不一样,锁被门窗调用,房子就是框架,卖给谁都行,谁买了装上自己的窗户和门就成了自己的家。所以你用框架,框架在调用你的类。而锁是一个工具类,你在调用锁。

用框架效率高,框架是一个半成品


HashSet用反射做

Collection collections=new HashSet(); HashSet()这个位置不是类的名字,而是配置文件读取出来的

新建文件,config.properties

source内容是

 className=java.util.ArrayList

ReflectTest2.java文件里加载properties文件用

InputStream ips=ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");


Properties属性文件在JAVA应用程序中是经常可以看得见的,也是特别重要的一类文件。它用来配置应用程序的一些信息,不过这些信息一般都是比较少的数据,没有必要使保存,而使用一般的文本文件来保存,如果是通过File直接保存的话,可能在存储和读取上都不是很方便,但如果保存为Properties文件就不一样了,属性文件都有键值对应的,在JAVA的包中,有提供专门的操作属性文件的类。这个类就是java.uitl.Properties类,由于Properties类是一个集合类,所以,Properties会将属性以集合的方式读写。

Properties类继承字Hashtable类,HashMap,采用键值对应的存储方式,在使用Properties类管理属性文件时有什么方便的 呢?Properties类有专门的读写方法来读写Properties属性文件,不用担心读写的格式问题,只要为Properties类提供一个读写流 即可。Properties用于读写属性文件的方法分别是

//读取属性文件流的方法 public void load(InputStream inStream) throws IOException {}//写属性文件流的方法 public void store(OutputStream out, String comments) throws IOException {} 

我们要做的第一步就是要将文件读取到Properties类对象中,由于load有一个参数是InputStream,所以我们可以用InputStream的子类FileInputStream将属性文件读取到Properties对象中,知道config.properties的路径, 我们就用FileInputStream(String name)构造函数:

InputStream ips=ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resource/config.properties");//从根开始的路径/* Properties等效一个HashMap(key yalue), * 但在HashMap上扩展了功能,可以把 自己内存中的键值对存到硬盘中 * 也可以在初始化的时候,从一个文件把自己的键值对加载进来,*/Properties props=new Properties();/* 建完Properties马上用load(读取属性文件流的方法)读取config.properties文件流*/ props.load(ips);/* * 马上关门,良好的习惯,如果没有关门:就会有一点小小的内存泄露,ips关联的系统资源没有被释放 * 这个内存泄露不是ips对象没有被释放,而是ips关联的系统资源没有被释放, * 例: * 本对象由java虚拟机作为垃圾进行回收 * 自己在被垃圾回收之前,先把自己关联的系统资源,物理资源干掉 * 如果不干掉,就是ips对象没了,但是以前只指向操作系统的资源还在 * ips由虚拟机管理的,有垃圾回收器来管理的,这样就把资源释放了 */ips.close();String className=props.getProperty("className");//反射Collection collections=(Collection)Class.forName(className).newInstance();//得到了类.调用不带参数的构造方法/* * 如果把ReflectPoint里的hashCode删掉,其他不变 * 可能会输出3 * 如果虽然两个对象pt1,pt2比较想等了,但是算的hashcode值,是按照你的内存算的,这 * 两个本来相同的值因为按照内存计算的 * 因为pt1与pt3取得区域可能不一样 * pt1会有内存值,pt3也会有内存值,这两个可能会相等 * 但只在一个区域里找*/ReflectPoint pt1=new ReflectPoint(3,3);ReflectPoint pt2=new ReflectPoint(5,5);ReflectPoint pt3=new ReflectPoint(3,3);collections.add(pt1);collections.add(pt2);collections.add(pt3);collections.add(pt1);/*  * collection里存完有两个值 * 移去一个应该还有一个,但打印出来是2 * 说明存完再改值后hashcode值也改了,不再一个区域内 * 这样就内存泄漏了 * 假如程序不断的增加删除修改对象,日积月累,内存就出现溢出的现象 */System.out.println(collections.size());

结果是:4


config.properties

内容改为

 className=java.util.HashSet();

结果变为:2


(七)类加载器

工程做完后,通常把bin文件下的class文件打成jar包

1、实际项目中,很少用相对路径

例如:InputStream ips=ReflectTest2.class.getResourceAsStream("config.properties");//相对路径

相对路径相对于

在运行里 输入

java MyClass  xx.file

xx.file文件是相对于当前工作目录去运算,这样不方便,

可以用绝对路径来解决

2、配置文件config.properties文件在哪里

 getRealPath()方法:得到项目的绝对位置

例如:安装了 “金山词霸”得到 金山词霸的位置,放到c盘得到c,放到d盘得到d,配置文件放在金山词霸内部的,

用金山词霸的绝对位置拼上内部位置,就得到一个完整的。


比如window-preferences-general-open click ,首选项打勾或不打勾,然后ok按钮,存起来

InputStream ips=new FileInputStream("config.properties");

如果要存,一定要完整路径

3、得到资源文件的方式,最常用的是InputStream,但是他不能替代FileInputStream

每一个.class文件,在用的时候,都要加载到内存里来,起这个作用的叫类加载器


既然可以加载.class文件,也可以加载普通文件

类加载器会提供一个方法

a、只要运行ReflectTest2.class这个类,一定被类加载器加载了,由类加载器getClassLoader加载进来,

getClassLoader可以加载.class文件

 也能加载普通文件,用getResourceAsStream()这个方法, 在classPath指定的目录下逐一的去查找要加载的文件
真正运行的时候是去classPath里去找,而不是源目录里去找

//InputStream ips=ReflectTest2.class.getClassLoader().getResourceAsStream("config.properties");//路径这么写是,去classPath下的根目录下找
//InputStream ips=ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");//相对路径,classPath下的路径里

框架的配置文件都是放在classPath指定的目录加载,都是用类加载器方式来加载文件,


b、配置文件在包里

class也提供了方法来加载资源文件,其实就是内部调用ClassLoader  

InputStream ips=ReflectTest2.class.getResourceAsStream("config.properties");//相对路径,相对于我的包而言的;

c、配置文件在包下面子包里

InputStream ips=ReflectTest2.class.getResourceAsStream("resource/config.properties");//相对路径,相对于本包的子包

c、从根目录开始的路径

InputStream ips=ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resource/config.properties");

配置文件的加载往往用类加载器,框架都是这么加的,用框架时,把配置文件放到classPath目录下

如果是eclipse开发就放到sourse下,或sourse字目录下,会自动拷贝到classPath下面去

(八)内省IntroSpector

用于对JavaBean进行操作

JavaBean是特殊的Java类,主要用于传递信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

这种JavaBean的实力对象称之为值对象(Value Object,简称VO)

例:

int getAge()

void setAge(int age)

符合这种特定规则的java类(get,set打头)我们称之为javaBean

能把javaBean当作普通类来操作

普通类不见得能当作j'avaBean来操作

class Person{

  private int x;//私有的,外面看不到

  public int getAge(){

       return  x;//返回内部一个局部变量

  }

  public void setAge(int age){

      this.x=age;//把传进来的参数给内部的那个变量

  }

}


把Person当成JavaBean来看,他有一个什么名称的属性(是age,不是x,x外面看不到)

把Person当成JavaBean来操作,设置的属性是age,不能说设置x

JavaBean的属性是根据方法名称来的

有一个特点,去掉set和get后,就是属性名,

如果第二个字母是小的,则把再把首字母改成小的,否则不变


1、内省案例

内省的方式读取JavaBean对象的x属性


package cn.test.day1;import java.beans.IntrospectionException;import java.beans.PropertyDescriptor;import java.lang.reflect.Method;public class IntroSpectorTest {/** * @param args * @throws Exception  */public static void main(String[] args) throws Exception {// TODO Auto-generated method stubReflectPoint pt1=new ReflectPoint(3,5);String prpertyName="x";/* * PropertyDescriptor代表了javabean的属性 * getClass把类当成javabean来看 * javabean的属性由get和set得出来的,进一步就可以得到这个属性的get方法和set方法 *  */PropertyDescriptor pd=new PropertyDescriptor(prpertyName,pt1.getClass());Method methodGetX=pd.getReadMethod();//得到x属性的读方法Object retVal=methodGetX.invoke(pt1);//在pt1上调用invoke,得到一个返回值System.out.println(retVal);}}

值为:3

取y的值

ReflectPoint pt1=new ReflectPoint(3,5);String prpertyName="x";/* * PropertyDescriptor代表了javabean的属性 * getClass把类当成javabean来看 * javabean的属性由get和set得出来的,进一步就可以得到这个属性的get方法和set方法 * 要是用javabean的话,取值一定要用get取 */PropertyDescriptor pd=new PropertyDescriptor(prpertyName,pt1.getClass());Method methodGetX=pd.getReadMethod();//得到x属性的读方法Object retVal=methodGetX.invoke(pt1);//在pt1上调用invoke,得到一个返回值System.out.println(retVal);//把y值set进去Method methodSetX=pd.getWriteMethod();methodSetX.invoke(pt1, 7);//set接受参数,把参数改为7,7的位置应该为对象,java5自动装箱System.out.println(pt1.getX());//y打印出来了


选中

PropertyDescriptor pd=new PropertyDescriptor(prpertyName,pt1.getClass());
Method methodGetX=pd.getReadMethod();//得到x属性的读方法
Object retVal=methodGetX.invoke(pt1);

右键->reflector->Extract Method...

方法的格式是某个方法接收两个参数,起名getProperty

方法就会生成

Object retVal = getProperty(pt1, prpertyName);
private static Object getProperty(Object pt1, String prpertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {PropertyDescriptor pd=new PropertyDescriptor(prpertyName,pt1.getClass());Method methodGetX=pd.getReadMethod();//得到x属性的读方法Object retVal=methodGetX.invoke(pt1);return retVal;


methodSetX.invoke(pt1, 7);

不是变量时没法重构,所以可以设成变量

Object value=7;//不为变量没法设

选中

                PropertyDescriptor pd2=new PropertyDescriptor(prpertyName,pt1.getClass());Method methodSetX=pd2.getWriteMethod();methodSetX.invoke(pt1, value);

重构
                Object value=7;//不为变量没法设setProperties(pt1, prpertyName, value);System.out.println(pt1.getX());}private static void setProperties(Object pt1, String prpertyName,Object value) throws IntrospectionException,IllegalAccessException, InvocationTargetException {PropertyDescriptor pd2=new PropertyDescriptor(prpertyName,pt1.getClass());Method methodSetX=pd2.getWriteMethod();methodSetX.invoke(pt1, value);}

2、内省的复杂案例

private static Object getProperty(Object pt1, String prpertyName)throws IntrospectionException, IllegalAccessException,InvocationTargetException {/*PropertyDescriptor pd=new PropertyDescriptor(prpertyName,pt1.getClass());Method methodGetX=pd.getReadMethod();//得到x属性的读方法Object retVal=methodGetX.invoke(pt1);*//*Introspector类中有getBeanInfo方法, * getBeanInfo:把java类(pt1.getClass())当成javaBean来看; * 看出来的结果用BeanInfo来表示, * BeanInfo就代表javaBean细节信息, * */BeanInfo beanInfo=Introspector.getBeanInfo(pt1.getClass());//PropertyDescriptor[] pds=beanInfo.getPropertyDescriptors();//所有的属性信息Object retVal=null;for(PropertyDescriptor pd:pds){if(pd.getName().equals(prpertyName)){Method methodGetX=pd.getReadMethod();//得到x属性的读方法retVal=methodGetX.invoke(pt1);break;}}return retVal;}

public static void main(String[] args) throws Exception {// TODO Auto-generated method stubReflectPoint pt1=new ReflectPoint(3,5);String prpertyName="x";/* * PropertyDescriptor代表了javabean的属性 * getClass把类当成javabean来看 * javabean的属性由get和set得出来的,进一步就可以得到这个属性的get方法和set方法 * 要是用javabean的话,取值一定要用get取 *  * 把methodGetX属性抽成一个方法 */Object retVal = getProperty(pt1, prpertyName);//在pt1上调用invoke,得到一个返回值System.out.println(retVal);}


原创粉丝点击