Java反射实战
一、背景
最近的项目中需要使用到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 package com.hafiz.zhang.Bean; 2 3 public class Person { 4 public Integer id; 5 private String name; 6 7 public Person() { 8 } 9 public Person(Integer id, String name) { 10 super(); 11 this.id = id; 12 this.name = name; 13 } 14 public Integer getId() { 15 return id; 16 } 17 public void setId(Integer id) { 18 this.id = id; 19 } 20 public String getName() { 21 return name; 22 } 23 public void setName(String name) { 24 this.name = name; 25 } 26 @Override 27 public String toString() { 28 return "Person [id=" + id + ", name=" + name + "]"; 29 } 30 31 public void sayHello() throws Exception{ 32 System.out.println("Hello Reflect!"); 33 } 34 }
1.使用反射获取对象所属类的全路径(包括报名和类名)
1 package com.hafiz.zhang.test; 2 3 import com.hafiz.zhang.Bean.Person; 4 5 /** 6 * @author hafiz.Zhang 7 * @Date 2016年5月18日 下午4:28:35 8 * @Description 测试通过一个对象获取该对象所属于的类的全路径(包括完整包名和类名) 9 */ 10 public class ReflectTest1 { 11 public static void main(String[] args) { 12 Person person = new Person(); 13 System.out.println("ClassName = " + person.getClass().getName()); 14 } 15 }
测试结果:
ClassName = com.hafiz.zhang.Bean.Person
2.测试使用反射实例化Class类对象
1 package com.hafiz.zhang.test; 2 3 import com.hafiz.zhang.Bean.Person; 4 5 /** 6 * @author hafiz.Zhang 7 * @Date 2016年5月18日 下午4:31:36 8 * @Description 测试获取Class类的三种方式 9 */ 10 public class ReflectTest2 { 11 public static void main(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 = new Person().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 package com.hafiz.zhang.test; 2 3 import com.hafiz.zhang.Bean.Person; 4 5 /** 6 * @author hafiz.Zhang 7 * @Date 2016年5月18日 下午4:38:15 8 * @Description 测试通过Class类对象实例化其他类 9 */ 10 public class ReflectTest3 { 11 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.InvocationTargetException; 5 6 import com.hafiz.zhang.Bean.Person; 7 8 /** 9 * @author hafiz.Zhang 10 * @Date 2016年5月18日 下午4:42:08 11 * @Description 测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象) 12 */ 13 public class ReflectTest4 { 14 public static void main(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 package com.hafiz.zhang.Bean; 2 3 /** 4 * @author hafiz.Zhang 5 * @Date 2016年5月19日 下午6:13:37 6 * @Description 动物接口 7 */ 8 public interface Animal { 9 public abstract void eat(); 10 public abstract void sleep(); 11 }
接口Skill.java
1 package com.hafiz.zhang.Bean; 2 3 /** 4 * @author hafiz.Zhang 5 * @Date 2016年5月19日 下午6:14:06 6 * @Description 技能接口 7 */ 8 public interface Skill { 9 public abstract void sayMiao(); 10 }
实现类:Cat.java
1 package com.hafiz.zhang.Bean; 2 3 public class Cat implements Animal, Skill { 4 private Integer num; 5 private String desc; 6 public Integer getNum() { 7 return num; 8 } 9 10 public void setNum(Integer num) { 11 this.num = num; 12 } 13 14 public String getDesc() { 15 return desc; 16 } 17 18 public void setDesc(String desc) { 19 this.desc = desc; 20 } 21 22 @Override 23 public void eat() { 24 System.out.println("cat eat fish"); 25 } 26 27 @Override 28 public void sleep() { 29 System.out.println("cat sleep in the day"); 30 } 31 32 @Override 33 public void sayMiao() { 34 System.out.println("cat say miao"); 35 } 36 37 public void sayHello(String name){ 38 System.out.println("Hello " + name); 39 } 40 }
测试类
1 package com.hafiz.zhang.test; 2 3 /** 4 * @author hafiz.Zhang 5 * @Date 2016年5月18日 下午4:51:29 6 * @Description 测试使用反射获取一个类实现的接口 7 */ 8 public class ReflectTest5 { 9 public static void main(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 package com.hafiz.zhang.test; 2 3 /** 4 * @author hafiz.Zhang 5 * @Date 2016年5月18日 下午5:03:25 6 * @Description 测试通过反射取得指定类的父类 7 */ 8 public class ReflectTest6 { 9 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.Modifier; 5 6 /** 7 * @author hafiz.Zhang 8 * @Date 2016年5月18日 下午5:06:02 9 * @Description 测试通过反射获得其他类中的全部构造函数 10 */ 11 public class ReflectTest7 { 12 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.Method; 4 import java.lang.reflect.Modifier; 5 6 /** 7 * @author hafiz.Zhang 8 * @Date 2016年5月18日 下午5:22:51 9 * @Description 测试通过反射获取类中的所有方法 10 */ 11 public class ReflectTest8 { 12 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.Modifier; 5 6 /** 7 * @author hafiz.Zhang 8 * @Date 2016年5月18日 下午5:38:09 9 * @Description 测试通过反射获取类中所有的属性 10 */ 11 public class ReflectTest9 { 12 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 6 /** 7 * @author hafiz.Zhang 8 * @Date 2016年5月19日 下午3:22:33 9 * @Description 测试使用反射调用指定类的方法 10 */ 11 public class ReflectTest10 { 12 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 6 /** 7 * @author hafiz.Zhang 8 * @Date 2016年5月19日 下午3:29:34 9 * @Description 测试通过反射调用其他类中的setter和getter方法 10 */ 11 public class ReflectTest11 { 12 public static void main(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 void getter(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.Field; 4 5 /** 6 * @author hafiz.Zhang 7 * @Date 2016年5月19日 下午3:41:59 8 * @Description 测试通过反射操作属性 9 */ 10 public class ReflectTest12 { 11 public static void main(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 package com.hafiz.zhang.test; 2 3 import java.lang.reflect.Array; 4 5 /** 6 * @author hafiz.Zhang 7 * @Date 2016年5月19日 下午4:52:21 8 * @Description 测试通过反射进行数组操作 9 * 10 */ 11 public class ReflectTest13 { 12 public static void main(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 void print(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 static Object 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 return newArr; 40 } 41 }
测试结果:
数组类型:java.lang.Integer
数组长度:6
数组第一个元素:1
修改之后数组第一个元素:8
=============反射修改数组长度=================
数组长度为:10
8 2 3 4 5 6 null null null null
感谢您花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让博主能喝上一杯咖啡,在此谢过了!
如果您觉得阅读本文对您有帮助,请点一下左下角“推荐”按钮,您的将是我最大的写作动力!另外您也可以选择【关注我】,可以很方便找到我!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/hafiz 欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利!