一、背景
最近的项目中需要使用到Java 反射的知识,以前不怎么了解,也基本没怎么用过,抽出一片时间,来具体学习和实战下Java的反射!拿来和大家分享以及记录方便以后学习!
二、反射相关概念解析
1.Class类
Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
如何得到各个类的字节码即Class类呢?
[1].类名.class:直接通过类.class获得。
[2].对象.getClass():通过对象调用其getClass方法获得。
[3].Class.forName("类全路径"):通过类加载器加载获得
注:Java中的原始基本类型:boolean, byte, char, short, int, long, float,double和关键词 void同样都有Class类,通过.class可获得它们的类字节码。
2.反射的概念
反射就是把Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,例如人是一个类,那么人的大脑、双手等也是一个个类。表示Java的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。
三、反射实战
测试Bean:Person.java
1 packagecom.hafiz.zhang.Bean;2
3 public classPerson {4 publicInteger id;5 privateString name;6
7 publicPerson() {8 }9 publicPerson(Integer id, String name) {10 super();11 this.id =id;12 this.name =name;13 }14 publicInteger getId() {15 returnid;16 }17 public voidsetId(Integer id) {18 this.id =id;19 }20 publicString getName() {21 returnname;22 }23 public voidsetName(String name) {24 this.name =name;25 }26 @Override27 publicString toString() {28 return "Person [id=" + id + ", name=" + name + "]";29 }30
31 public void sayHello() throwsException{32 System.out.println("Hello Reflect!");33 }34 }
1.使用反射获取对象所属类的全路径(包括报名和类名)
1 packagecom.hafiz.zhang.test;2
3 importcom.hafiz.zhang.Bean.Person;4
5 /**
6 *@authorhafiz.Zhang7 * @Date 2016年5月18日 下午4:28:358 * @Description 测试通过一个对象获取该对象所属于的类的全路径(包括完整包名和类名)9 */
10 public classReflectTest1 {11 public static voidmain(String[] args) {12 Person person = newPerson();13 System.out.println("ClassName = " +person.getClass().getName());14 }15 }
测试结果:
ClassName = com.hafiz.zhang.Bean.Person
2.测试使用反射实例化Class类对象
1 packagecom.hafiz.zhang.test;2
3 importcom.hafiz.zhang.Bean.Person;4
5 /**
6 *@authorhafiz.Zhang7 * @Date 2016年5月18日 下午4:31:368 * @Description 测试获取Class类的三种方式9 */
10 public classReflectTest2 {11 public static voidmain(String[] args) {12 Class> obj1 = null;13 Class> obj2 = null;14 Class> obj3 = null;15 try{16 //一般尽量要采用这种方式进行实例化Class类对象
17 obj1 = (Class>) Class.forName("com.hafiz.zhang.Bean.Person");18 } catch(ClassNotFoundException e) {19 e.printStackTrace();20 }21 obj2 = newPerson().getClass();22 obj3 = Person.class;23
24 System.out.println("ClassName:" +obj1.getName());25 System.out.println("ClassName:" +obj2.getName());26 System.out.println("ClassName:" +obj3.getName());27 }28 }
测试结果:
ClassName:com.hafiz.zhang.Bean.Person
ClassName:com.hafiz.zhang.Bean.Person
ClassName:com.hafiz.zhang.Bean.Person
3.测试通过Class类对象实例化其他类
1 packagecom.hafiz.zhang.test;2
3 importcom.hafiz.zhang.Bean.Person;4
5 /**
6 *@authorhafiz.Zhang7 * @Date 2016年5月18日 下午4:38:158 * @Description 测试通过Class类对象实例化其他类9 */
10 public classReflectTest3 {11 public static voidmain(String[] args) {12 Class> clazz = null;13 try{14 clazz = Class.forName("com.hafiz.zhang.Bean.Person");15 } catch(ClassNotFoundException e) {16 e.printStackTrace();17 }18 Person person = null;19 try{20 person =(Person) clazz.newInstance();21 } catch(InstantiationException e) {22 e.printStackTrace();23 } catch(IllegalAccessException e) {24 e.printStackTrace();25 }26 if(null !=person) {27 person.setId(1);28 person.setName("Hafiz.Zhang");29 System.out.println("person=" +person);30 }else{31 System.out.println("实例化对象失败");32 }33 }34 }
测试结果:
person=Person [id=1, name=Hafiz.Zhang]
4.测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.Constructor;4 importjava.lang.reflect.InvocationTargetException;5
6 importcom.hafiz.zhang.Bean.Person;7
8 /**
9 *@authorhafiz.Zhang10 * @Date 2016年5月18日 下午4:42:0811 * @Description 测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)12 */
13 public classReflectTest4 {14 public static voidmain(String[] args) {15 Class> clazz = null;16 try{17 clazz = Class.forName("com.hafiz.zhang.Bean.Person");18 } catch(ClassNotFoundException e) {19 e.printStackTrace();20 }21 Person p1 = null;22 Person p2 = null;23 Constructor>[] cs =clazz.getConstructors();24 try{25 p1 = (Person) cs[0].newInstance();//通过无参构造获得对象26 p2 = (Person) cs[1].newInstance(1, "Hafiz.Zhang");//通过有参构造获得对象27 } catch(InstantiationException e) {28 e.printStackTrace();29 } catch(IllegalAccessException e) {30 e.printStackTrace();31 } catch(IllegalArgumentException e) {32 e.printStackTrace();33 } catch(InvocationTargetException e) {34 e.printStackTrace();35 }36 System.out.println("Person1=" +p1);37 System.out.println("Person2=" +p2);38 }39 }
测试结果:
Person1=Person [id=null, name=null]
Person2=Person [id=1, name=Hafiz.Zhang]
5.测试使用反射获取一个类实现的接口
接口Animal.java
1 packagecom.hafiz.zhang.Bean;2
3 /**
4 *@authorhafiz.Zhang5 * @Date 2016年5月19日 下午6:13:376 * @Description 动物接口7 */
8 public interfaceAnimal {9 public abstract voideat();10 public abstract voidsleep();11 }
接口Skill.java
1 packagecom.hafiz.zhang.Bean;2
3 /**
4 *@authorhafiz.Zhang5 * @Date 2016年5月19日 下午6:14:066 * @Description 技能接口7 */
8 public interfaceSkill {9 public abstract voidsayMiao();10 }
实现类:Cat.java
1 packagecom.hafiz.zhang.Bean;2
3 public class Cat implementsAnimal, Skill {4 privateInteger num;5 privateString desc;6 publicInteger getNum() {7 returnnum;8 }9
10 public voidsetNum(Integer num) {11 this.num =num;12 }13
14 publicString getDesc() {15 returndesc;16 }17
18 public voidsetDesc(String desc) {19 this.desc =desc;20 }21
22 @Override23 public voideat() {24 System.out.println("cat eat fish");25 }26
27 @Override28 public voidsleep() {29 System.out.println("cat sleep in the day");30 }31
32 @Override33 public voidsayMiao() {34 System.out.println("cat say miao");35 }36
37 public voidsayHello(String name){38 System.out.println("Hello " +name);39 }40 }
测试类
1 packagecom.hafiz.zhang.test;2
3 /**
4 *@authorhafiz.Zhang5 * @Date 2016年5月18日 下午4:51:296 * @Description 测试使用反射获取一个类实现的接口7 */
8 public classReflectTest5 {9 public static voidmain(String[] args) {10 Class> clazz = null;11 try{12 clazz = Class.forName("com.hafiz.zhang.Bean.Cat");13 } catch(ClassNotFoundException e) {14 e.printStackTrace();15 }16 Class>[] interfaces =clazz.getInterfaces();17 System.out.println("Cat实现的接口有");18 for(Class>cl : interfaces) {19 System.out.println(cl.getName());20 }21 }22 }
测试结果:
Cat实现的接口有
com.hafiz.zhang.Bean.Animal
com.hafiz.zhang.Bean.Skill
6.测试通过反射取得指定类的父类
1 packagecom.hafiz.zhang.test;2
3 /**
4 *@authorhafiz.Zhang5 * @Date 2016年5月18日 下午5:03:256 * @Description 测试通过反射取得指定类的父类7 */
8 public classReflectTest6 {9 public static voidmain(String[] args) {10 Class> clazz = null;11 try{12 clazz = Class.forName("com.hafiz.zhang.Bean.Cat");13 } catch(ClassNotFoundException e) {14 e.printStackTrace();15 }16 Class> superClass =clazz.getSuperclass();17 System.out.println("SuperClass=" +superClass);18 }19 }
测试结果:SuperClass=class com.hafiz.zhang.Bean.Person
7.测试通过反射获得其他类中的全部构造函数
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.Constructor;4 importjava.lang.reflect.Modifier;5
6 /**
7 *@authorhafiz.Zhang8 * @Date 2016年5月18日 下午5:06:029 * @Description 测试通过反射获得其他类中的全部构造函数10 */
11 public classReflectTest7 {12 public static voidmain(String[] args) {13 Class> clazz = null;14 try{15 clazz = Class.forName("com.hafiz.zhang.Bean.Person");16 } catch(ClassNotFoundException e) {17 e.printStackTrace();18 }19 Constructor>[] cs =clazz.getConstructors();20 //实现方式1
21 /*for(Constructor> item : cs) {22 System.out.println("构造方法:" + item.getName());23 }*/
24 //实现方式2
25 for(Constructor>item : cs) {26 System.out.print("构造方法:");27 System.out.print(Modifier.toString(item.getModifiers()) + " ");28 System.out.print(item.getName() + "(");29 Class>[] paramterTypes =item.getParameterTypes();30 for(int i = 0; i < paramterTypes.length; i++) {31 System.out.print(paramterTypes[i].getName() + " arg" +i);32 if(i < paramterTypes.length-1) {33 System.out.print(",");34 }35 }36 System.out.println(")");37 }38 }39 }
测试结果:
构造方法:public com.hafiz.zhang.Bean.Person()
构造方法:public com.hafiz.zhang.Bean.Person(java.lang.Integer arg0,java.lang.String arg1)
8. 测试通过反射获取类中的所有方法(包括方法包含的异常)
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.Method;4 importjava.lang.reflect.Modifier;5
6 /**
7 *@authorhafiz.Zhang8 * @Date 2016年5月18日 下午5:22:519 * @Description 测试通过反射获取类中的所有方法10 */
11 public classReflectTest8 {12 public static voidmain(String[] args) {13 Class> clazz = null;14 try{15 clazz = Class.forName("com.hafiz.zhang.Bean.Person");16 } catch(ClassNotFoundException e) {17 e.printStackTrace();18 }19 Method[] methods =clazz.getDeclaredMethods();20 for(Method method : methods) {21 Class> returnType =method.getReturnType();22 System.out.print(Modifier.toString(method.getModifiers()) + " ");23 System.out.print(returnType.getName() + " " + method.getName() + "(");24 Class>[] paras =method.getParameterTypes();25 for(int i = 0 ; i < paras.length ; i++) {26 System.out.print(paras[i].getName() + " arg" +i);27 if(i < paras.length - 1) {28 System.out.print(",");29 }30 }31 Class>[] exces =method.getExceptionTypes();32 if(exces.length > 0) {33 System.out.print(") throws ");34 for(int j = 0; j < exces.length; j++) {35 System.out.print(exces[j].getName());36 if(j < exces.length - 1) {37 System.out.print(", ");38 }39 }40 }else{41 System.out.print(")");42 }43 System.out.println();44 }45 }46 }
测试结果:
public java.lang.String toString()
public java.lang.String getName()
public void setName(java.lang.String arg0)
public java.lang.Integer getId()
public void sayHello() throws java.lang.Exception
public void setId(java.lang.Integer arg0)
9.测试通过反射获取类中所有的属性
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.Field;4 importjava.lang.reflect.Modifier;5
6 /**
7 *@authorhafiz.Zhang8 * @Date 2016年5月18日 下午5:38:099 * @Description 测试通过反射获取类中所有的属性10 */
11 public classReflectTest9 {12 public static voidmain(String[] args) {13 Class> clazz = null;14 try{15 clazz = Class.forName("com.hafiz.zhang.Bean.Cat");16 } catch(ClassNotFoundException e) {17 e.printStackTrace();18 }19 Field[] fields =clazz.getDeclaredFields();20 System.out.println("=========通过反射获取指定类中所有的属性=========");21 for(Field field : fields) {22 System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getType().getName() + " " +field.getName());23 }24 System.out.println("=========通过反射获取指定类实现的接口或者父类中所有的属性=========");25 Field[] fields2 =clazz.getSuperclass().getDeclaredFields();26 for(Field item : fields2) {27 System.out.println(Modifier.toString(item.getModifiers()) + " " + item.getType() + " " +item.getName());28 }29 }30 }
测试结果:
=========通过反射获取指定类中所有的属性=========
private java.lang.Integer num
private java.lang.String desc
=========通过反射获取指定类实现的接口或者父类中所有的属性=========
public class java.lang.Integer id
private class java.lang.String name
10.测试使用反射调用指定类的方法
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.InvocationTargetException;4 importjava.lang.reflect.Method;5
6 /**
7 *@authorhafiz.Zhang8 * @Date 2016年5月19日 下午3:22:339 * @Description 测试使用反射调用指定类的方法10 */
11 public classReflectTest10 {12 public static voidmain(String[] args) {13 Class> clazz = null;14 try{15 clazz = Class.forName("com.hafiz.zhang.Bean.Cat");16 } catch(ClassNotFoundException e) {17 e.printStackTrace();18 }19 try{20 //调用Cat类中的eat无参方法
21 Method method = clazz.getMethod("eat");22 method.invoke(clazz.newInstance());23 //调用Cat类中的sayHello有参方法
24 Method method2 = clazz.getDeclaredMethod("sayHello", String.class);25 method2.invoke(clazz.newInstance(), "Hafiz.Zhang");26 } catch(NoSuchMethodException e) {27 e.printStackTrace();28 } catch(SecurityException e) {29 e.printStackTrace();30 } catch(IllegalAccessException e) {31 e.printStackTrace();32 } catch(IllegalArgumentException e) {33 e.printStackTrace();34 } catch(InvocationTargetException e) {35 e.printStackTrace();36 } catch(InstantiationException e) {37 e.printStackTrace();38 }39 }40 }
测试结果:
cat eat fish
Hello Hafiz.Zhang
11.测试通过反射调用其他类中的setter和getter方法
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.InvocationTargetException;4 importjava.lang.reflect.Method;5
6 /**
7 *@authorhafiz.Zhang8 * @Date 2016年5月19日 下午3:29:349 * @Description 测试通过反射调用其他类中的setter和getter方法10 */
11 public classReflectTest11 {12 public static voidmain(String[] args) {13 Class> clazz = null;14 Object obj = null;15 try{16 clazz = Class.forName("com.hafiz.zhang.Bean.Cat");17 obj =clazz.newInstance();18 } catch(ClassNotFoundException e) {19 e.printStackTrace();20 } catch(InstantiationException e) {21 e.printStackTrace();22 } catch(IllegalAccessException e) {23 e.printStackTrace();24 }25 getter(obj,"Desc");26 setter(obj,"Desc","测试调用set方法",String.class);27 getter(obj,"Desc");28 }29
30 private static voidgetter(Object obj, String name) {31 try{32 Method method = obj.getClass().getMethod("get"+name);33 System.out.println(name + ":" +method.invoke(obj));34 } catch(NoSuchMethodException e) {35 e.printStackTrace();36 } catch(SecurityException e) {37 e.printStackTrace();38 } catch(IllegalAccessException e) {39 e.printStackTrace();40 } catch(IllegalArgumentException e) {41 e.printStackTrace();42 } catch(InvocationTargetException e) {43 e.printStackTrace();44 }45 }46
47 private static void setter(Object obj, String name, String desc, Class>type) {48 try{49 Method method = obj.getClass().getMethod("set" +name, type);50 method.invoke(obj, desc);51 } catch(NoSuchMethodException e) {52 e.printStackTrace();53 } catch(SecurityException e) {54 e.printStackTrace();55 } catch(IllegalAccessException e) {56 e.printStackTrace();57 } catch(IllegalArgumentException e) {58 e.printStackTrace();59 } catch(InvocationTargetException e) {60 e.printStackTrace();61 }62 }63 }
测试结果:
Desc:null
Desc:测试调用set方法
12.测试通过反射操作属性
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.Field;4
5 /**
6 *@authorhafiz.Zhang7 * @Date 2016年5月19日 下午3:41:598 * @Description 测试通过反射操作属性9 */
10 public classReflectTest12 {11 public static voidmain(String[] args) {12 Class> clazz = null;13 Object obj = null;14 try{15 clazz = Class.forName("com.hafiz.zhang.Bean.Cat");16 obj =clazz.newInstance();17 Field field = clazz.getDeclaredField("desc");18 //若要设置private属性,需要设置
19 field.setAccessible(true);//设置成员变量可访问,包括private成员变量(暴力反射),private成员通过这步操作才能被访问20 field.set(obj, "this is test demo");21 System.out.println("Desc=" +field.get(obj));22 } catch(ClassNotFoundException e) {23 e.printStackTrace();24 } catch(InstantiationException e) {25 e.printStackTrace();26 } catch(IllegalAccessException e) {27 e.printStackTrace();28 } catch(NoSuchFieldException e) {29 e.printStackTrace();30 } catch(SecurityException e) {31 e.printStackTrace();32 }33
34 }35 }
测试结果:Desc=this is test demo
13.测试通过反射进行数组操作
1 packagecom.hafiz.zhang.test;2
3 importjava.lang.reflect.Array;4
5 /**
6 *@authorhafiz.Zhang7 * @Date 2016年5月19日 下午4:52:218 * @Description 测试通过反射进行数组操作9 *10 */
11 public classReflectTest13 {12 public static voidmain(String[] args) {13 Integer[] array = {1,2,3,4,5,6};14 Class> clazz =array.getClass().getComponentType();15 System.out.println("数组类型:" +clazz.getName());16 System.out.println("数组长度:" +Array.getLength(array));17 System.out.println("数组第一个元素:" + Array.get(array, 0));18 Array.set(array, 0, 8);19 System.out.println("修改之后数组第一个元素:" + Array.get(array, 0));20 System.out.println("=============反射修改数组长度=================");21 Integer[] arr2 = (Integer[])changeLength(array, 10);22 print(arr2);23 }24 private static voidprint(Object obj) {25 Class> clazz =obj.getClass();26 if(!clazz.isArray()) {27 return;28 }29 System.out.println("数组长度为:" +Array.getLength(obj));30 for(int i = 0; i < Array.getLength(obj); i++){31 System.out.print(Array.get(obj, i) + " ");32 }33 }34 public staticObject changeLength(Object obj, Integer length){35 Class> clazz =obj.getClass().getComponentType();36 Object newArr =Array.newInstance(clazz, length);37 Integer len =Array.getLength(obj);38 System.arraycopy(obj, 0, newArr, 0, len);39 returnnewArr;40 }41 }
测试结果:
数组类型:java.lang.Integer
数组长度:6
数组第一个元素:1
修改之后数组第一个元素:8
=============反射修改数组长度=================
数组长度为:10
8 2 3 4 5 6 null null null null