标签:show 就是 efi demo bst 总结 res play 不同的
一、啥是反射?
通过反射机制加载一个class字节码文件,获得并调用任意一个类的所有属性和方法。
二、反射能干啥?
三、干一干试试看!
1. Animal样本类
public class Animal { public String name = "Dog"; private int age = 3; public Animal(){ System.out.println("Public-Animal"); } public Animal(String name){ System.out.println("Public-Animal:name"+name); } private Animal(String name, int age){ System.out.println("Private-Animal:name:" + name + ",age:" + age ); } public String sayName(String name){ return "Hello," + name; } }
2. ReflectTest测试类
public class ReflectTest { public static void main(String[] args) throws Exception { //获取Class对象的三种方式 Class animal = Class.forName("com.reflect.Animal"); Class animal_2 = Animal.class; Animal animalObj = new Animal(); Class animal_3 = animalObj.getClass(); System.out.println(animal);//class com.reflect.Animal System.out.println(animal_2);//class com.reflect.Animal System.out.println(animal_3);//class com.reflect.Animal System.out.println(animal == animal_2);//true System.out.println(animal == animal_3);//true //获得成员变量 //1.获得所有声明的成员变量 Field[] declaredFieldList = animal.getDeclaredFields(); for(Field field : declaredFieldList){ System.out.println("DeclaredField"+field); //DeclaredFieldpublic java.lang.String com.reflect.Animal.name //DeclaredFieldprivate int com.reflect.Animal.age } //2.获得所有共有的成员变量 Field[] pubFieldList = animal.getFields(); for(Field field : pubFieldList){ System.out.println("PublicField" + field); //PublicFieldpublic java.lang.String com.reflect.Animal.name } //获得构造器 //1.获得所有声明的构造器 Constructor[] declaredConst = animal.getDeclaredConstructors(); for(Constructor constructor : declaredConst){ System.out.println(constructor); //private com.reflect.Animal(java.lang.String,int) //public com.reflect.Animal(java.lang.String) //public com.reflect.Animal() } //2.获得所有共有的构造器 Constructor[] pubConst = animal.getConstructors(); for(Constructor constructor : pubConst){ System.out.println(constructor); //public com.reflect.Animal(java.lang.String) //public com.reflect.Animal() } //获得非构造方法,具体不演示了 //1.获得所有声明非构造方法 Method[] declaredMethodList = animal.getDeclaredMethods(); //获得公有非构造方法 Method[] methodList = animal.getMethods(); } }
3. 进阶测试类
public class ReflectDemo { public static void main(String[] args) throws Exception { // 1.通过字符串获取Class对象,这个字符串必须带上完整路径名 Class animalClass = Class.forName("com.reflect.Animal"); // 2.获取声明的构造方法,传入所需参数的类名,如果有多个参数,用‘,‘连接即可, private Animal(String name, int age) Constructor animalConstructor = animalClass.getDeclaredConstructor(String.class, Integer.class); // 如果是私有的构造方法,需要调用下面这一行代码使其可使用,公有的构造方法则不需要下面这一行代码 animalConstructor.setAccessible(true); // 使用构造方法的newInstance方法创建对象,传入构造方法所需参数,如果有多个参数,用‘,‘连接即可 Object animal = animalConstructor.newInstance("Cat",100); // 3.获取声明的字段,传入字段名 private int age = 3; Field animalgeField = animalClass.getDeclaredField("age"); // 如果是私有的字段,需要调用下面这一行代码使其可使用,公有的字段则不需要下面这一行代码 animalgeField.setAccessible(true); // 使用字段的set方法设置字段值,传入此对象以及参数值 animalgeField.set(animal,10);
// 4.获取声明的函数,传入所需参数的类名,如果有多个参数,用‘,‘连接即可 Method studentShowMethod = animalClass.getDeclaredMethod("sayName", String.class); // 如果是私有的函数,需要调用下面这一行代码使其可使用,公有的函数则不需要下面这一行代码 //studentShowMethod.setAccessible(true); // 使用函数的invoke方法调用此函数,传入此对象以及函数所需参数,如果有多个参数,用‘,‘连接即可。函数会返回一个Object对象,使用强制类型转换转成实际类型即可 Object result = studentShowMethod.invoke(animal,"message"); System.out.println("result: " + result);//result: Hello,message,age:10
}
}
四、为啥这么搞,不是更复杂了吗?
为啥不直接使用当前类的方法属性,而是利用反射通过class文件获取呢?
举例:Spring IOC容器进行Bean管理,在Spring中我们经常看到:
Spring就是通过配置文件中class路径进行反射处理获得对应的对象。这样便可以根据不同的配置进行相应的处理。而不需要每次都要new一个,不把代码写死。
//解析<bean .../>元素的id属性得到该字符串值为"sqlSessionFactory" String idStr = "sqlSessionFactory"; //解析<bean .../>元素的class属性得到该字符串值为"org.mybatis.spring.SqlSessionFactoryBean" String classStr = "org.mybatis.spring.SqlSessionFactoryBean"; //利用反射知识,通过classStr获取Class类对象 Class cls = Class.forName(classStr); //实例化对象 Object obj = cls.newInstance(); //container表示Spring容器 container.put(idStr, obj); //当一个类里面需要用另一类的对象时,我们继续下面的操作 //解析<property .../>元素的name属性得到该字符串值为“dataSource” String nameStr = "dataSource"; //解析<property .../>元素的ref属性得到该字符串值为“dataSource” String refStr = "dataSource"; //生成将要调用setter方法名 String setterName = "set" + nameStr.substring(0, 1).toUpperCase() + nameStr.substring(1); //获取spring容器中名为refStr的Bean,该Bean将会作为传入参数 Object paramBean = container.get(refStr); //获取setter方法的Method类,此处的cls是刚才反射代码得到的Class对象 Method setter = cls.getMethod(setterName, paramBean.getClass()); //调用invoke()方法,此处的obj是刚才反射代码得到的Object对象 setter.invoke(obj, paramBean);
总结:
标签:show 就是 efi demo bst 总结 res play 不同的
原文地址:https://www.cnblogs.com/qmillet/p/12503090.html