JAVA入门难点之反射和内省
反射(java.lang.reflect)
反射机制:java类中的各成员映射成对应的类的实例对象,然后再进行操作。
反射就是运行时获取一个类的所有信息,可以获取到.class的任何定义的信息(包括成员 变量(字段),成员方法,构造器等)
2. 任何数据类型(包括基本数据类型)都有一个“静态”的class属性。
3. 通过Class类的静态方法:forName(String className)(常用)。
1 @Test 2 public void test() throws Exception { 3 // 通过class.forName加载类 4 Class cla = Class.forName("com.cn.reflect.Person"); 5 // 直接通过类名.class 6 Class cla1 = Person.class; 7 // 通过对象名.getClass()方法 8 Class cla2 = new Person().getClass(); 9 }
2.通过反射获取构造器
注意如果类中是一个私有的构造器,需添加如下代码:强制访问(暴力访问),获取私有构造器
Constructor c=getDeclaredConstructor(int.class); c.setAccessible(true);
1 @Test 2 public void test1() throws Exception { 3 // 加载Person类 4 Class cla = Class.forName("com.cn.reflect.Person"); 5 // 通过getConstructor()方法获取无参的构造器 6 // Constructor constructor = cla.getConstructor(); 7 // 通过getConstructor()方法获取有参的构造器 8 Constructor constructor2 = cla.getConstructor(String.class); 9 // 实例化构造器 10 Person p = (Person) constructor2.newInstance("zhangsan"); 11 }
3.通过反射获取方法
1 @Test 2 public void test3() throws Exception { 3 Person p = new Person(); 4 Class cla = Class.forName("com.cn.reflect.Person"); 5 Method method = cla.getMethod("b", int.class); 6 method.invoke(p, 55); 7
4.通过反射获取字段
1 @Test 2 public void test4() throws Exception { 3 Person p = new Person(); 4 Class cla = Class.forName("com.cn.reflect.Person"); 5 Field field = cla.getDeclaredField("age"); 6 field.setAccessible(true); 7 System.out.println(field.get(p)); 8 9 10 }
内省(java.beans.Introspector)
内省(Introspector) 是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法。
内省基于反射实现,主要用于操作JavaBean,通过内省 可以获取bean的getter/setter方法。
JavaBean
JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。
通过查看api,了解到JavaBean常用的两个方法:
在使用JavaBean时记住导入: commons-beanutils-1.9.2.jar 架包
Animal实体类:
1 package com.cn.bean; 2 3 public class Animal { 4 private String name; 5 private int id; 6 private String type; 7 public String getName() { 8 return name; 9 } 10 public void setName(String name) { 11 this.name = name; 12 } 13 public int getId() { 14 return id; 15 } 16 public void setId(int id) { 17 this.id = id; 18 } 19 public String getType() { 20 return type; 21 } 22 public void setType(String type) { 23 this.type = type; 24 } 25 26 }
JavaBean测试:
1 @Test 2 public void test2() throws Exception { 3 4 String name = "xxx"; 5 int id = 01; 6 String type = "猫科"; 7 8 Animal a = new Animal(); 9 BeanUtils.setProperty(a, "name", name); 10 BeanUtils.setProperty(a, "id", id); 11 BeanUtils.setProperty(a, "type", type); 12 13 System.out.println(a.getName()); 14 System.out.println(a.getId()); 15 System.out.println(a.getType()); 16 } 17 }
运行结果:
xxx
1
猫科
Introspector类:
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。
User类:
package com.cn.ycl; public class User { private String name; private int age; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
测试:
1 @Test 2 public void test1() throws Exception { 3 // BeanInfo beanInfo = Introspector.getBeanInfo(User.class);//可以获取到age,addres,age,class(父类的) 4 BeanInfo beanInfo = Introspector.getBeanInfo(User.class, Object.class); 5 PropertyDescriptor[] pd = beanInfo.getPropertyDescriptors(); 6 for (PropertyDescriptor pdr : pd) { 7 System.out.println(pdr.getName()); 8 } 9 }
运行结果:获取到User类中的字段,属性方法。
通过内省得到name的Get,Set方法,给name设置“xxxx”,然后通过getReadMethod()方法取出来,打印输出
1 @Test 2 public void test2() throws Exception { 3 PropertyDescriptor pd = new PropertyDescriptor("name", User.class); 4 User u = new User(); 5 Method method = pd.getWriteMethod();//相当于User类中的setName()方法 7 method.invoke(u, "xxxx"); 8 method = pd.getReadMethod();//相当于User类中getName()方法 9 String invoke = (String) method.invoke(u, null); 10 System.out.println(invoke); 11 } 12 }
运行结果 :xxxx
二、内省和反射区别:
区别:
反射式在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态。
内省机制是通过反射来实现的,BeanInfo用来暴露一个bean的属性、方法和事件,以后我们就可以操纵该JavaBean的属性
内省操作只针对JavaBean,只有符合JavaBean规则的类的成员才可以采用内省API进行操作
内省是Java语言对Bean类属性、事件的一种缺省处理方法。例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。通过getName/setName来访问name属性,这就是默认的规则。Java中提供了一套API用来访问某个属性的getter/setter方法,通过这些API可以使你不需要了解这个规则,这些API存放于包java.beans中。
一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以调用这些方法。