为什么需要反射?
需求:我公司定义了一组接口,然后第三方公司按照我公司的接口实现了一套功能,然后交给我们,但是我们公司的项目已经结束,如何实现动态加载第三方公司提供的功能。(类似于热拔插效果)
什么是反射?
反射就是八类中的各种成分映射成各种对象。等同于解刨,可以拿到类中任何成分。
反射常用类:
- Class:获取类和类的成员信息
- Filed:可访问的类的属性
- Method:类的方法
- Constructor:类的构造方法
使用反射基本步骤:
- 1.导入java.lang.reflect.*
- 2.获得需要操作的类的Java.lang.Class对象
- 3.调用Class的方法获取Field、Method等对象
- 4.使用反射API进行操作(设置属性﹑调用方法)
获取类对象的方法:
- 通过对象----person.getClass();
- 通过类名----Person.class;
- 通过Class.forName("xxxx");------Class.forName("xxxxxx");
获取类的类对象后可以获取类中的属性、构造方法、非构造方法
现获取类对象 : Class<?> clazz = Class.forName("xxxx.xxx.xxPerson");
【0】动态创建对象
方法一:使用Class的newInstance()方法,仅适用于无参构造方法
Class clazz=Class.forName("com.qf.reflection.Student");
Object obj=clazz.newInstance();
方法二:调用Constructor的newInstance()方法,适用所有构造方法
Constructor cons = clazz.getConstructor(new Class[]{ String.class, int.class, float.class });
Object obj = cons.newInstance(new Object[ ] {"lkl", 32, 56.5f });
【1】获取属性可以获取全部属性,也可以获取单个属性
1.获取全部属性用的类是Field[] , ---------- Field[] declaredFields = clazz.getDeclaredFields();
2.获取单个属性用的类是Field, ----------- Field name = clazz.getDeclaredField("name");
注:Declared这个关键字获取私有的必须要带上,如果想修改private属性,必须先修改权限可以访问 如:name.setAccessible(true);
public static void getField() throws Exception{ //1获取类对象 Class<?> clazz = Class.forName("com.qf.Person"); //2获取 Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } //获取单个 System.out.println("--------------------------"); Field name = clazz.getDeclaredField("name"); // // Person wangwu=new Person(); // wangwu.name="王五"; Object wangwu = clazz.newInstance(); //赋值 name.setAccessible(true); name.set(wangwu, "王五");// wangwu.name="王五"; //获取 Object object=name.get(wangwu);// wangwu.name System.out.println(object); }
【2】 反射出构造方法
第一步仍然是现获取类对象
1.获取所有的构造方法(不包括私有化的构造方法)
Constructor<?>[] constructors = clazz.getConstructors();
2.获取单个构造方法(无参)
Constructor<?> constructor = clazz.getConstructor();
2.获取单个构造方法(有参)
Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
注:利用有参和无参的构造方法可以创建对象
1(无参)Object lisi = clazz.getConstructor().newInstance();
2(有参)clazz.getConstructor(String.class, int.class, String.class).newInstance("王五", 20, "男");
public static void getConstructor() throws Exception{ Class<?> clazz=Class.forName("com.qf.Person"); //1获取构造方法 Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor); } System.out.println("--------------------------"); //2获取单个构造方法 //2.1获取无参构造方法 Constructor<?> constructor = clazz.getConstructor(); //2.2获取带参 Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, String.class); System.out.println(constructor); System.out.println(constructor1); //3利用构造方法创建对象 System.out.println("---------利用构造方法创建对象------------"); Person zhangsan=new Person(); Object lisi = constructor.newInstance(); System.out.println(zhangsan); System.out.println(lisi); Object wangwu = constructor1.newInstance("王五", 20, "男"); System.out.println(wangwu); //简单创建对象的方法 Object o = clazz.newInstance(); System.out.println(o.toString()); }
【获取非构造方法】
仍然是先创建类对象 Class<?> clazz=Class.forName("xxx.xxx.Person");
1.获取所有的公开方法,包括自己和父类的
Method[] methods = clazz.getMethods();
2.获取公类自己所有的方法,包括非公开的方法
Method[] methods = clazz.getDeclaredMethods();
3 获取单个方法(无参)
Method show = clazz.getMethod("show");
show.invoke(zhangsan);// zhangsan.show();
注:必须要指定对象 invoke(obj p)
public static void getMethod() throws Exception{ //1获取无参的方法 Class<?> clazz=Class.forName("com.qf.Person"); //Method[] methods = clazz.getMethods();//获取公类自己公开的方法,继承的公开方法 // Method[] methods = clazz.getDeclaredMethods();//获取公类自己所有的方法,包括非公开的方法 // System.out.println("-----------getMethods();----------"); // for (Method method : methods) { // System.out.println(method); // } // Person p=new Person(); // p.show(); Object zhangsan = clazz.newInstance(); Method show = clazz.getMethod("show"); show.invoke(zhangsan);// zhangsan.show(); //2获取有参 Method show2=clazz.getMethod("show",String.class); show2.invoke(zhangsan, "北京"); //3获取带返回值的方法 Method getInfo = clazz.getMethod("getInfo"); Object value=getInfo.invoke(zhangsan); System.out.println(value); //4获取静态方法 Method print = clazz.getMethod("print"); print.invoke(null);// Person.print(); //5私有方法 Method show3 = clazz.getDeclaredMethod("show", String.class, String.class); //设置访问权限无效 show3.setAccessible(true); show3.invoke(zhangsan, "上海","zhangsan@qq.com"); }
注:Java ,内省机制,是一种使用反射获取或设置对象属性的一种方式
- Introspector 内省类
- BeanInfo 类的信息
- PropertyDescriptor 属性描述符
public class Demo { public static void main(String[] args) throws Exception{ CarManager carManager=new CarManager(); //car Field car = CarManager.class.getDeclaredField("car"); Class<?> carClass = car.getType(); //获取注解 CarAnnotation annotation = car.getAnnotation(CarAnnotation.class); Object o = carClass.newInstance(); //Java ,内省机制,是一种使用反射获取或设置对象属性的一种方式 // Introspector 内省类 // BeanInfo 类的信息 // PropertyDescriptor 属性描述符 Class<?> clazz3=CarAnnotation.class; //1使用内省类Introspector获取类信息对象 BeanInfo beanInfo = Introspector.getBeanInfo(carClass); //2调用类信息的getPropertyDescriptors()获取属性描述符 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); //3遍历 for (PropertyDescriptor pd : propertyDescriptors) { //System.out.println(pd.getName()); //System.out.println(pd.getName()); String name=pd.getName();//属性 try { Method method = clazz3.getMethod(name); if(method!=null){ Object value = method.invoke(annotation); Method writeMethod = pd.getWriteMethod(); writeMethod.invoke(o,value); } } catch (Exception e) { continue; } } System.out.println(o.toString()); } }