一.什么是反射,反射有什么用
以前我们创建对象有几种方式?只有一种方式去new一个对象。有的时候在程序的开发阶段,你并不知道要创建哪
个类的对象,或者你不知道要调用类的哪个方法,或者访问类的哪个属性。在程序的运行阶段,你才知道要创建哪
个类的对象。那怎么解决这种问题?
研究一下spring的核心的源码的业务逻辑,分以下几个步骤
1,读取applicationContext.xml,获取所有的bean标签的class属性
2,获取bean标签的class属性之后,class属性的值在java程序中应该以什么数据类型来存储,用字符串类型来存储
3,根据class属性的字符串描述符来创建一个这个描述符描述的对象。需求到这一步,就变成:
根据一个字符串,来创建一个字符串描述的对象。
使用反射必须先获取类的Class对象,每个类在java的虚拟机中,默认都会存在一个class的对象。如果要使用反
射,必须先获取这个Class对象。
二.class对象的使用
1.Class对象获取的三种方式
创建Person.java
package com.aaa.spring.entity; /** * 人员类 */ public class Person { }
/** * Class对象获取的三种方式 */ public class Test02 { public static void main(String[] args) throws Exception { //获取Person的Class对象 //第一种方式,通过Class.forName() Class clazz1 = Class.forName("com.aaa.spring.entity.Person"); System.out.println(clazz1); //第二种方式 访问类的class对象 Class clazz2 = Person.class; System.out.println(clazz2); //第三种方式,通过对象的getClass方法 Person person = new Person(); Class clazz3 = person.getClass(); System.out.println(clazz3); } }
2.利用Class对象获取构造方法
创建Person2.java
package com.aaa.spring.entity; public class Person2 { //默认无参的构造 public Person2(){} //公共的有一个参数的方法 public Person2(String name){} //私有的有两个参数的方法 private Person2(String name,int age){} }
/** * 利用CLass对象获取构造方法 */ public class Test03 { public static void main(String[] args) throws Exception { //获取类的Class对象 Class clazz = Person2.class; //获取类的所有公共的构造方法 Constructor[] constructors = clazz.getConstructors(); for (Constructor con : constructors) { System.out.println(con); } System.out.println("==="); //获取类的所有的声明的构造方法 Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor con : declaredConstructors ) { System.out.println(con); } //根据参数获取指定的构造方法 System.out.println("获取指定一个参数的公共的构造方法:"); Constructor con1 = clazz.getConstructor(String.class); System.out.println(con1); System.out.println("获取两个参数的私有的构造方法:"); Constructor con2 = clazz.getDeclaredConstructor(String.class, int.class); System.out.println(con2); } }
3.利用Class对象获取类的方法
创建Person3.java
package com.aaa.spring.entity; public class Person3 { public void info(){ System.out.println("我是一个无参的公共方法"); } public void info(String name,int age){ System.out.println("我是一个有两个参数的额公共方法"); } private void info(String name){ System.out.println("我是一个有一个参数的私有的方法"); } }
/** * 利用Class对象获取方法 */ public class Test04 { public static void main(String[] args) throws Exception { //获取类的Class对象 Class clazz = Person3.class; Method[] methods = clazz.getMethods(); System.out.println("获取类的所有的公共的方法,包含父类的方法:"); for (Method method: methods) { System.out.println(method); } System.out.println("获取所有的声明的方法:"); Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method method: declaredMethods) { System.out.println(method); } System.out.println("获取两个参数的公共的方法:"); Method method = clazz.getMethod("info",String.class,int.class); System.out.println(method); System.out.println("获取一个参数的私有的方法:"); Method method2 = clazz.getDeclaredMethod("info",String.class); System.out.println(method2); } }
4.利用Class对象获取类的属性
创建Person4.java
package com.aaa.spring.entity; public class Person4 extends Person{ public String name; private int age; }
public class Test05 { public static void main(String[] args) throws Exception{ //获取类的Class对象 Class clazz = Person4.class; System.out.println("获取类的所有公共的属性(也包括父类中的公共的属性):"); Field[] fields = clazz.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println("获取类的所有声明的属性:"); Field[] declaredFields = clazz.getDeclaredFields(); for (Field field: declaredFields ) { System.out.println(field); } //获取公共的name属性 System.out.println("获取公共的name属性"); Field name = clazz.getField("name"); System.out.println(name); System.out.println("获取私有的age属性:"); Field age = clazz.getDeclaredField("age"); System.out.println(age); } }
5.利用Class对象创建类的实例
创建Person5.java
package com.aaa.spring.entity; public class Person5 { private String name; //默认无参的构造 public Person5(){} //公共的有一个参数的方法 public Person5(String name){ this.name=name; } //私有的有两个参数的方法 private Person5(String name,int age){} public void info(){ System.out.println(name); } }
/** * 利用CLass对象创建类的实例 */ public class Test06 { public static void main(String[] args) throws Exception { //获取类的class对象 Class clazz = Class.forName("com.aaa.spring.entity.Person5"); //创建类的对象有两种方式 //第一种,调用Class对象的newInstance方法,该方法会会调用类的默认的无参的构造 Person5 person51 =(Person5) clazz.newInstance(); System.out.println(person51); //第二种,根据类的构造方法对象创建类的实例 Constructor constructor = clazz.getConstructor(String.class); Person5 person52 = (Person5)constructor.newInstance("zhangsan"); System.out.println(person52); person52.info(); Constructor con2 = clazz.getDeclaredConstructor(String.class, int.class); //设置忽略构造方法的访问级别 con2.setAccessible(true); Person5 person53 = (Person5)con2.newInstance("zhangsan", 18); person53.info(); } }
6.利用Class对象调用类的方法
创建Person6.java
package com.aaa.spring.entity; public class Person6 { public void info(){ System.out.println("我是一个无参的公共方法"); } public void info(String name,int age){ System.out.println("我是一个有两个参数的额公共方法"); } private void info(String name){ System.out.println("我是一个有一个参数的私有的方法"); } }
/** * 利用Class对象访问类的方法 */ public class Test07 { public static void main(String[] args) throws Exception { Person6 p6 = new Person6(); p6.info(); p6.info("zhangsan",12); //获取类的Class对象 Class clazz = Class.forName("com.aaa.spring.entity.Person6"); //利用反射创建对象 Object p61 = clazz.newInstance(); //获取info()方法 Method info = clazz.getMethod("info"); //调用用法 info.invoke(p61); //获取info(string,int)这个方法 Method info1 = clazz.getMethod("info", String.class, int.class); //调用方法 info1.invoke(p61,"张三",16); //利用反射调用类的私有的方法 Method info2 = clazz.getDeclaredMethod("info",String.class); //忽略方法的访问级别 info2.setAccessible(true); //调用方法 info2.invoke(p61,"李四"); } }
7.利用Class对象返回类的属性
创建Person7.java
package com.aaa.spring.entity; public class Person7 { public String name="zhangsan"; private int age=12; }
/** * 利用Class对象访问类的属性 */ public class Test08 { public static void main(String[] args) throws Exception { Person7 p = new Person7(); String name = p.name; System.out.println(name); p.name="lisi"; System.out.println(p.name); //获取类的CLass对象 Class clazz = Class.forName("com.aaa.spring.entity.Person7"); //获取对象的属性值,打印出来 //创建对象 Object p1 = clazz.newInstance(); //获取类的属性的对象 Field f1 = clazz.getField("name"); //设置属性的值 f1.set(p1,"lisi"); //获取属性的值 Object name1 = f1.get(p1); System.out.println(name1.toString()); Field f2 = clazz.getDeclaredField("age"); //忽略访问级别 f2.setAccessible(true); System.out.println(f2.get(p1)); } }