一、反射
1.为什么需要反射?
因为我们在某些情况不知道传入的参数的真是类型,所以需要用反射来操作,获取到真实类型,进而去调用我们需要的构造器、方法、字段等。
2.获取字节码对象
①使用类的全限定名来获取字节码对象
Class clz = Class.forName("com.wjw.class._01_test.Person");
②使用对象来获取字节码对象
Person p = new Person();
Class clz = p.getClass();
③使用类名的方式来获取字节码对象
Class clz = Person.class;
3.使用字节码对象获取构造器:
①获取所有构造器
Construtor[] cs = clz.getConstrutors();
②获取所有构造器(包括私有化构造器)
Construtor[] dcs = clz.getDeclaredConstrutors();
③获取指定构造器(里面的参数传入的是构造器参数类型的类对象)
Construtor c = clz.getConstrutor(String.class,Integer.class);
④获取指定的私有化构造器
Construtor dc = clz.getDeclaredConstrutor(String.class);
4.调用构造器
①调用指定构造器
Person p = c.getInstance("猪八戒",18);
②调用指定的私有化构造器
dc.setAccessible(true);
Person p = dc.getInstance("杨戬");
注意:需要将私有化的设置成可以访问才能进行调用
③直接调用无参构造器生成对象(类必须要有无参构造器)
Person p = clz.newInstance();
5.获取和调用方法
①获取所有方法
Method[] ms = clz.getMethods();
注意:这里获取的所有方法包括父类继承下来的方法
②获取本类中的所有的方法
Method[] dms = clz.getDeclaredMethods();
注意:这里获取的方法是本类的公共和私有方法
③获取指定的方法
Method m = clz.getMethod("方法名",参数列表的对象);
Method m = clz.getMethod("get",String.class);
④获取指定私有化方法
Method dm = clz.getDeclaredMethod("set",Integer.class);
⑤调用公共方法
Person p = clz.newInstance();
m.invoke(p,"张三");
⑥调用私有化方法
Person p = clz.newInstance();
dm.setAccessible(true);
dm.invoke(p,18);
二、内省
1.内省的作用
我们在用反射调用方法时非常的繁琐,如果想调用getter、setter方法时,还需要写两次繁琐的操作,因此SUN公司提供了一套操作JavaBean属性的API,方便我们去调用getter、setter方法
2.属性
前面是get、set的方法后面的名字就是属性
3.使用内省操作JavaBean
①将JavaBean转为BeanInfo
Class<Person> clz = Person.class;
Person p = clz.newInstance();
BeanInfo bif = Introspector.getBeanInfo(clz,Object.class);
注意:第二个参数的作用是“终点”,这样就不会获取到Object中的属性
②获取所有属性
PropertyDescriptor[] pds = bif.getPropertyDescriptors();
③获取属性的名字、类型、setter、getter方法
for (PropertyDescriptor pd : pds) {
pd.getName();
pd.getPropertyType();
pd.getWriteMethod();
pd.getReadMethod();
}
④案例:调用setter方法中的属性为name进行设置值
if ("name".equals(pd.getName())) {
pd.getWriteMethod.invoke(p,"庞德");
}
⑤案例:调用getter方法中的属性为name进行获取值
if ("name".equals(pd.getName())) {
Object name = pd.getReadMethod.invoke(p);
System.out.println(name);
}