反射
为什么需要反射勒(作用)?
我们编写工具类,需要调用操作类的真实对象时,而我们开始编写工具类并不知道类的真实数据类型是什么,其中还涉及类的强转,但是不知道类真实类型是什么,也不知道类的真实对象是什么,这个时候就需要运用反射来通过一个对象获取真实类型以及调用该对象中的方法
什么是反射?
在程序运行中,通过字节码对象,去获取类中的成员,进而操作它们(目的);
那么什么是字节码对象呢
程序加载类,假设我们不知道类里面是什么东东,但是我们可以确定里面有类的成员(感觉像是废话),JAVA想干什么都得找其对应的对象,而我们可以把这些字节码归为一个大的Class类,而Class的对象就是字节码对象,细分我们还可以对字段,构造器,方法也都把它们看做对应的一个类(抽取公共部分),再通过其类的对象去操作字段呀构造器还有方法(想搞谁,就找对象,对象的API有对应的方法操作),
反射怎么操作(方法)?
要进行反射操作,首先得找Class的对象,但是Class的对象在程序加载的时候就创建了(jvm操作字节码得找字节码对象),字节码对象的获取的途径有:方式一 对象.getClass;方式二 类.class;方式三:用Class.forName全限定名(包名.类名)(用方式三,其他的都知道具体对象了)
public static Class getAclass1(Student student){
Class aClass = student.getClass();
return aClass;
}
public static Class getAclass2(){
Class aclass = Student.class;
return aclass;
}
public static Class getAclass3(String domainName ) throws ClassNotFoundException {
Class aClass = Class.forName(domainName);
return aClass;
}
下面列举一般的个别API操作:
//构造器对象获取 constructor
public static Constructor[] getConstructor1(Class aclass){
Constructor[] constructors = aclass.getConstructors();//获取全部公共的构造器对象
System.out.println("constructors = " + constructors);
return constructors;
}
public static Constructor[] getConstructor2(Class aclass){
Constructor[] declaredConstructors = aclass.getDeclaredConstructors();//获取全部的构造器对象
return declaredConstructors;
}
public static Constructor getConstructor3(Class aclass) throws NoSuchMethodException {
Constructor constructor = aclass.getConstructor(aclass);//获取单个公共构造器
return constructor;
}
public static Constructor getConstructor4(Class aclass) throws NoSuchMethodException {
Constructor declaredConstructor = aclass.getDeclaredConstructor(String.class);//获取全部类型的单个构造器
return declaredConstructor;
}
//获取真实对象
public static <T> T getRealInstance(Constructor<T> constructor) throws IllegalAccessException, InvocationTargetException, InstantiationException {
T instance = constructor.newInstance();//通过构造器对象获取
return instance;
}
//获取指定方法并执行该方法
public static void getMethod(Class aclass) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Method println = aclass.getMethod("println");
println.invoke(aclass.newInstance());
}
//字段设置
public static String getFile(Class aclass) throws Exception{
Field name = aclass.getDeclaredField("name");
name.setAccessible(true);
Object i = aclass.newInstance();
name.set(i,"二狗");
String j =(String) name.get(i);
return j;
}
内省(Introsperctor)
内省是API提供专门操作javabean属性的,入口是introspector;
与反射不同的是,反射通过字节码对象获得实例对象可以暴力直接对私有化字段方法进行操作,违反当初类封装的初衷,而内省不是对Class字节码对象直接操作,而是把字节码对象装在beaninfo里面,再get获得所有成员(字段和对应设置器访问器方法)对象存在PropertyDescriptor数组,遍历操作即可,代码演示:
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class IntrospectorDemo {
public static void main(String[] args) throws Exception {
Class<?> aclass = Class.forName("cn.wolfcode.Student");
Object o = aclass.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(aclass);//拿出来装在beanInfo里面
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String name = propertyDescriptor.getName();//获取字段名字
Method readMethod = propertyDescriptor.getReadMethod();//获取字段访问器的方法
Method writeMethod = propertyDescriptor.getWriteMethod();//获取字段设置器的方法
System.out.println("name = " + name);
System.out.println("readMethod = " + readMethod);
System.out.println("writeMethod = " + writeMethod);
System.out.println("=======================");
}
//测试javabean转map
Map<String, java.lang.Object> map = JavaBeanToMap(aclass);
// System.out.println(map);
//测试map转javabean
Map<String,Object> map1 = new HashMap<>();
Student student = MapToJavaBean(map, Student.class);
System.out.println(student);
}
//javabean-->map
public static Map<String,Object> JavaBeanToMap(Class aclass) throws Exception{
Map<String,Object> map = new HashMap<>();
Object o = aclass.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(aclass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String name = propertyDescriptor.getName();
Method readMethod = propertyDescriptor.getReadMethod();
Method writeMethod = propertyDescriptor.getWriteMethod();
map.put(name,readMethod.invoke(aclass.newInstance()));
}
return map;
}
//map-->javabean
public static <T> T MapToJavaBean (Map<String,Object> map,Class<T> aclass) throws Exception{
T instance = aclass.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(aclass, Object.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
String key = propertyDescriptor.getName();
Object value = map.get(key);
propertyDescriptor.getWriteMethod().invoke(instance,value);
}
return instance;
}
}
public class Student {
private String name = "大狗";
private int age = 18;
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;
}
public Student() {
System.out.println("creatConstrutor1");
}
public Student(String name) {
System.out.println("creatConstrutor2");
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public void println(){
System.out.println("\"println\" = " + "println");
}
}