Java反射实战

时间:2021-10-27 01:26:32

一、背景

  最近的项目中需要使用到Java 反射的知识,以前不怎么了解,也基本没怎么用过,抽出一片时间,来具体学习和实战下Java的反射!拿来和大家分享以及记录方便以后学习!

二、反射相关概念解析

1.Class类

  Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。

  如何得到各个类的字节码即Class类呢?

    [1].类名.class:直接通过类.class获得。

    [2].对象.getClass():通过对象调用其getClass方法获得。  

    [3].Class.forName("类全路径"):通过类加载器加载获得

  注:Java中的原始基本类型:boolean, bytecharshortintlongfloat,double和关键词 void同样都有Class类,通过.class可获得它们的类字节码。

2.反射的概念

  反射就是把Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,例如人是一个类,那么人的大脑、双手等也是一个个类。表示Java的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

  一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。

三、反射实战

测试Bean:Person.java

 package com.hafiz.zhang.Bean;

 public class Person {
public Integer id;
private String name; public Person() {
}
public Person(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
} public void sayHello() throws Exception{
System.out.println("Hello Reflect!");
}
}

1.使用反射获取对象所属类的全路径(包括报名和类名)

 package com.hafiz.zhang.test;

 import com.hafiz.zhang.Bean.Person;

 /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午4:28:35
* @Description 测试通过一个对象获取该对象所属于的类的全路径(包括完整包名和类名)
*/
public class ReflectTest1 {
public static void main(String[] args) {
Person person = new Person();
System.out.println("ClassName = " + person.getClass().getName());
}
}

测试结果:

ClassName = com.hafiz.zhang.Bean.Person

2.测试使用反射实例化Class类对象

 package com.hafiz.zhang.test;

 import com.hafiz.zhang.Bean.Person;

 /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午4:31:36
* @Description 测试获取Class类的三种方式
*/
public class ReflectTest2 {
public static void main(String[] args) {
Class<?> obj1 = null;
Class<?> obj2 = null;
Class<?> obj3 = null;
try {
//一般尽量要采用这种方式进行实例化Class类对象
obj1 = (Class<?>) Class.forName("com.hafiz.zhang.Bean.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
obj2 = new Person().getClass();
obj3 = Person.class; System.out.println("ClassName:" + obj1.getName());
System.out.println("ClassName:" + obj2.getName());
System.out.println("ClassName:" + obj3.getName());
}
}

测试结果:

ClassName:com.hafiz.zhang.Bean.Person
ClassName:com.hafiz.zhang.Bean.Person
ClassName:com.hafiz.zhang.Bean.Person

3.测试通过Class类对象实例化其他类

 package com.hafiz.zhang.test;

 import com.hafiz.zhang.Bean.Person;

 /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午4:38:15
* @Description 测试通过Class类对象实例化其他类
*/
public class ReflectTest3 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person person = null;
try {
person = (Person) clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if(null != person) {
person.setId(1);
person.setName("Hafiz.Zhang");
System.out.println("person=" + person);
}else{
System.out.println("实例化对象失败");
}
}
}

测试结果:

person=Person [id=1, name=Hafiz.Zhang]

4.测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

 package com.hafiz.zhang.test;

 import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import com.hafiz.zhang.Bean.Person; /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午4:42:08
* @Description 测试通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
*/
public class ReflectTest4 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person p1 = null;
Person p2 = null;
Constructor<?>[] cs = clazz.getConstructors();
try {
p1 = (Person) cs[0].newInstance();//通过无参构造获得对象
p2 = (Person) cs[1].newInstance(1, "Hafiz.Zhang");//通过有参构造获得对象
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println("Person1=" + p1);
System.out.println("Person2=" + p2);
}
}

测试结果:

Person1=Person [id=null, name=null]
Person2=Person [id=1, name=Hafiz.Zhang]

5.测试使用反射获取一个类实现的接口

接口Animal.java

 package com.hafiz.zhang.Bean;

 /**
* @author hafiz.Zhang
* @Date 2016年5月19日 下午6:13:37
* @Description 动物接口
*/
public interface Animal {
public abstract void eat();
public abstract void sleep();
}

接口Skill.java

 package com.hafiz.zhang.Bean;

 /**
* @author hafiz.Zhang
* @Date 2016年5月19日 下午6:14:06
* @Description 技能接口
*/
public interface Skill {
public abstract void sayMiao();
}

实现类:Cat.java

 package com.hafiz.zhang.Bean;

 public class Cat implements Animal, Skill  {
private Integer num;
private String desc;
public Integer getNum() {
return num;
} public void setNum(Integer num) {
this.num = num;
} public String getDesc() {
return desc;
} public void setDesc(String desc) {
this.desc = desc;
} @Override
public void eat() {
System.out.println("cat eat fish");
} @Override
public void sleep() {
System.out.println("cat sleep in the day");
} @Override
public void sayMiao() {
System.out.println("cat say miao");
} public void sayHello(String name){
System.out.println("Hello " + name);
}
}

测试类

 package com.hafiz.zhang.test;

 /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午4:51:29
* @Description 测试使用反射获取一个类实现的接口
*/
public class ReflectTest5 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?>[] interfaces = clazz.getInterfaces();
System.out.println("Cat实现的接口有");
for(Class<?> cl : interfaces) {
System.out.println(cl.getName());
}
}
}

测试结果:

Cat实现的接口有
com.hafiz.zhang.Bean.Animal
com.hafiz.zhang.Bean.Skill

6.测试通过反射取得指定类的父类

 package com.hafiz.zhang.test;

 /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午5:03:25
* @Description 测试通过反射取得指定类的父类
*/
public class ReflectTest6 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?> superClass = clazz.getSuperclass();
System.out.println("SuperClass=" + superClass);
}
}

测试结果:SuperClass=class com.hafiz.zhang.Bean.Person

7.测试通过反射获得其他类中的全部构造函数

 package com.hafiz.zhang.test;

 import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier; /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午5:06:02
* @Description 测试通过反射获得其他类中的全部构造函数
*/
public class ReflectTest7 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?>[] cs = clazz.getConstructors();
//实现方式1
/*for(Constructor<?> item : cs) {
System.out.println("构造方法:" + item.getName());
}*/
//实现方式2
for(Constructor<?> item : cs) {
System.out.print("构造方法:");
System.out.print(Modifier.toString(item.getModifiers()) + " ");
System.out.print(item.getName() + "(");
Class<?>[] paramterTypes = item.getParameterTypes();
for(int i = 0; i < paramterTypes.length; i++) {
System.out.print(paramterTypes[i].getName() + " arg" + i);
if(i < paramterTypes.length-1) {
System.out.print(",");
}
}
System.out.println(")");
}
}
}

测试结果:

构造方法:public com.hafiz.zhang.Bean.Person()
构造方法:public com.hafiz.zhang.Bean.Person(java.lang.Integer arg0,java.lang.String arg1)

8. 测试通过反射获取类中的所有方法(包括方法包含的异常)

 package com.hafiz.zhang.test;

 import java.lang.reflect.Method;
import java.lang.reflect.Modifier; /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午5:22:51
* @Description 测试通过反射获取类中的所有方法
*/
public class ReflectTest8 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods) {
Class<?> returnType = method.getReturnType();
System.out.print(Modifier.toString(method.getModifiers()) + " ");
System.out.print(returnType.getName() + " " + method.getName() + "(");
Class<?>[] paras = method.getParameterTypes();
for(int i = 0 ; i < paras.length ; i++) {
System.out.print(paras[i].getName() + " arg" + i);
if(i < paras.length - 1) {
System.out.print(",");
}
}
Class<?>[] exces = method.getExceptionTypes();
if(exces.length > 0) {
System.out.print(") throws ");
for(int j = 0; j < exces.length; j++) {
System.out.print(exces[j].getName());
if(j < exces.length - 1) {
System.out.print(", ");
}
}
}else{
System.out.print(")");
}
System.out.println();
}
}
}

测试结果:

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.测试通过反射获取类中所有的属性

 package com.hafiz.zhang.test;

 import java.lang.reflect.Field;
import java.lang.reflect.Modifier; /**
* @author hafiz.Zhang
* @Date 2016年5月18日 下午5:38:09
* @Description 测试通过反射获取类中所有的属性
*/
public class ReflectTest9 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] fields = clazz.getDeclaredFields();
System.out.println("=========通过反射获取指定类中所有的属性=========");
for(Field field : fields) {
System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getType().getName() + " " + field.getName());
}
System.out.println("=========通过反射获取指定类实现的接口或者父类中所有的属性=========");
Field[] fields2 = clazz.getSuperclass().getDeclaredFields();
for(Field item : fields2) {
System.out.println(Modifier.toString(item.getModifiers()) + " " + item.getType() + " " + item.getName());
}
}
}

测试结果:

=========通过反射获取指定类中所有的属性=========
private java.lang.Integer num
private java.lang.String desc
=========通过反射获取指定类实现的接口或者父类中所有的属性=========
public class java.lang.Integer id
private class java.lang.String name

10.测试使用反射调用指定类的方法

 package com.hafiz.zhang.test;

 import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; /**
* @author hafiz.Zhang
* @Date 2016年5月19日 下午3:22:33
* @Description 测试使用反射调用指定类的方法
*/
public class ReflectTest10 {
public static void main(String[] args) {
Class<?> clazz = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//调用Cat类中的eat无参方法
Method method = clazz.getMethod("eat");
method.invoke(clazz.newInstance());
//调用Cat类中的sayHello有参方法
Method method2 = clazz.getDeclaredMethod("sayHello", String.class);
method2.invoke(clazz.newInstance(), "Hafiz.Zhang");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}

测试结果:

cat eat fish
Hello Hafiz.Zhang

11.测试通过反射调用其他类中的setter和getter方法

 package com.hafiz.zhang.test;

 import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; /**
* @author hafiz.Zhang
* @Date 2016年5月19日 下午3:29:34
* @Description 测试通过反射调用其他类中的setter和getter方法
*/
public class ReflectTest11 {
public static void main(String[] args) {
Class<?> clazz = null;
Object obj = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
obj = clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
getter(obj,"Desc");
setter(obj,"Desc","测试调用set方法",String.class);
getter(obj,"Desc");
} private static void getter(Object obj, String name) {
try {
Method method = obj.getClass().getMethod("get"+name);
System.out.println(name + ":" + method.invoke(obj));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} private static void setter(Object obj, String name, String desc, Class<?> type) {
try {
Method method = obj.getClass().getMethod("set" + name, type);
method.invoke(obj, desc);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}

测试结果:

Desc:null
Desc:测试调用set方法

12.测试通过反射操作属性

 package com.hafiz.zhang.test;

 import java.lang.reflect.Field;

 /**
* @author hafiz.Zhang
* @Date 2016年5月19日 下午3:41:59
* @Description 测试通过反射操作属性
*/
public class ReflectTest12 {
public static void main(String[] args) {
Class<?> clazz = null;
Object obj = null;
try {
clazz = Class.forName("com.hafiz.zhang.Bean.Cat");
obj = clazz.newInstance();
Field field = clazz.getDeclaredField("desc");
//若要设置private属性,需要设置
field.setAccessible(true);//设置成员变量可访问,包括private成员变量(暴力反射),private成员通过这步操作才能被访问
field.set(obj, "this is test demo");
System.out.println("Desc=" + field.get(obj));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} }
}

测试结果:Desc=this is test demo

13.测试通过反射进行数组操作

 package com.hafiz.zhang.test;

 import java.lang.reflect.Array;

 /**
* @author hafiz.Zhang
* @Date 2016年5月19日 下午4:52:21
* @Description 测试通过反射进行数组操作
*
*/
public class ReflectTest13 {
public static void main(String[] args) {
Integer[] array = {1,2,3,4,5,6};
Class<?> clazz = array.getClass().getComponentType();
System.out.println("数组类型:" + clazz.getName());
System.out.println("数组长度:" + Array.getLength(array));
System.out.println("数组第一个元素:" + Array.get(array, 0));
Array.set(array, 0, 8);
System.out.println("修改之后数组第一个元素:" + Array.get(array, 0));
System.out.println("=============反射修改数组长度=================");
Integer[] arr2 = (Integer[])changeLength(array, 10);
print(arr2);
}
private static void print(Object obj) {
Class<?> clazz = obj.getClass();
if(!clazz.isArray()) {
return;
}
System.out.println("数组长度为:" + Array.getLength(obj));
for(int i = 0; i < Array.getLength(obj); i++){
System.out.print(Array.get(obj, i) + " ");
}
}
public static Object changeLength(Object obj, Integer length){
Class<?> clazz = obj.getClass().getComponentType();
Object newArr = Array.newInstance(clazz, length);
Integer len = Array.getLength(obj);
System.arraycopy(obj, 0, newArr, 0, len);
return newArr;
}
}

测试结果:

数组类型:java.lang.Integer
数组长度:6
数组第一个元素:1
修改之后数组第一个元素:8
=============反射修改数组长度=================
数组长度为:10
8 2 3 4 5 6 null null null null