1.Java反射机制是什么?
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以运行时再装配,无需在组件之间进行源代码链接,但是反射使用不当会导致成本很高。
Java反射机制主要提供了以下功能:
- 在运行时判断任意一个对象的所属类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
2.Java Reflection
Reflection是实现Java反射机制的一个关键性质,反射机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public、static等)、 superclass(例如Object)、实现了的 interfaces (例如Serializable)、也包括其fields和methods的所有信息,并可于运行时改变fields内容或调用methods。
在JDK中主要由以下类开实现Java反射机制,
这些类(除了Class类)都位于java.lang.reflect包中。
- Class类:代表一个类,位于java.lang包下。
- Field类:代表类的成员变量(成员变量也称为类的属性)。
- Method类:代表类的方法。
- Constructor类:代表类的构造方法。
- Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
Java反射机制通常借助Class、Field、Method和Constructor这四个类实现,其中最核心的就是Class类,它是反射的基础,在应用反射机制的过程中我们最关心的一般是一个类的构造器(Constructor类)、属性(Field类)和方法(Method类),下面我们主要介绍Class类和Class类中针对这三个元素的方法:
1)Class类
- getName() -- 这个类型的全限定名
- getSuperClass() -- 这个类型的直接超类的全限定名
- isInterface() -- 这个类型是类类型还是接口类型
- getTypeParamters() -- 这个类型的访问修饰符
- getInterfaces() -- 任何直接超接口的全限定名的有序列表
- getFields() -- 字段信息
- getMethods() -- 方法信息
2)Field类
- Field getField(String name) -- 获得命名的公共字段
- Field[] getFields() -- 获得类的所有公共字段
- Field getDeclaredField(String name) -- 获得类声明的命名的字段
- Field[] getDeclaredFields() -- 获得类声明的所有字段
3)Method类
- Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法
- Method[] getMethods() -- 获得类的所有公共方法
- Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法
- Method[] getDeclaredMethods() -- 获得类声明的所有方法
3.具体实现
1)通过一个对象获得完整的包名和类名
ReflectionTest test = new ReflectionTest();
System.out.println("ReflectionTest的包名为:" + test.getClass().getName());
//实例化Class类对象
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
class1 = Class.forName("reflection.ReflectionTest");
class2 = new ReflectionTest().getClass();
class3 = ReflectionTest.class;
System.out.println("class1的类名为:" + class1.getName());
System.out.println("class2的类名为:" + class2.getName());
System.out.println("class3的类名为:" + class3.getName());
2)获取一个对象的父类与实现的接口
Class<?> class4 = Class.forName("reflection.ReflectionTest");
//获取父类
Class<?> parentClass4 = class4.getSuperclass();
System.out.println("class4的父类为:" + parentClass4.getName());
//获取所实现的接口
Class<?> interfaceClass4[] = class4.getInterfaces();
System.out.println("class4实现的接口有:");
for(int i = 0; i < interfaceClass4.length; i++)
{
System.out.println((i + 1) + ":" + interfaceClass4[i].getName());
}
3)通过反射机制实例化一个类的对象
package reflection;
//User类
public class User
{
private int age;
private String name;
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public void reflect1()
{
System.out.println("Java 反射机制——调用User类中的reflect1()方法");
}
public void reflect2(int age, String name)
{
System.out.println("Java 反射机制——调用User类中的reflect2()方法");
System.out.println("Name—> " + name + " Age—> " + age);
}
}
Class<?> class5 = Class.forName("reflection.User");
//实例化默认构造方法,调用set进行赋值,调用get进行取值
User user = (User) class5.newInstance();
user.setAge(18);
user.setName("Tom");
System.out.println("Name = " + user.getName() + " Age = " + user.getAge());
4)获取某个类的全部属性
Class<?> class6 = Class.forName("reflection.ReflectionTest");
//取得本类的全部属性
Field[] field1 = class6.getDeclaredFields();
System.out.println("===============本类属性===============");
for(int i = 0; i < field1.length; i++)
{
//权限修饰符
int mod1 = field1[i].getModifiers();
String modifier1 = Modifier.toString(mod1);
//属性类型
Class<?> type = field1[i].getType();
System.out.println("属性类型为:" + type + " 权限修饰符为:" + modifier1 + "\n");
}
//取得实现的接口或者父类的属性
Field[] field2 = class6.getFields();
System.out.println("==========实现的接口或者父类的属性==========");
for(int i = 0; i < field2.length; i++)
{
//权限修饰符
int mod2 = field2[i].getModifiers();
String modifier2 = Modifier.toString(mod2);
//属性类型
Class<?> type = field2[i].getType();
System.out.println("属性类型为:" + type + " 权限修饰符为:" + modifier2 + "\n");
}
5)获取某个类的全部方法
Class<?> class7 = Class.forName("reflection.User");
//得到类中的全部方法
Method method[] = class7.getMethods();
System.out.println("============获取类的全部方法============");
for(int i = 0; i < method.length; i++)
{
//得到方法的返回类型
Class<?> returnType = method[i].getReturnType();
//得到方法的全部参数
Class<?> parameter[] = method[i].getParameterTypes();
int temp = method[i].getModifiers();
//得到方法的权限修饰符
System.out.print(Modifier.toString(temp) + " ");
//得到方法的返回类型
System.out.print(returnType.getName() + " ");
//得到方法名
System.out.print(method[i].getName() + " ");
System.out.print("(");
//得到方法的参数
for (int j = 0; j < parameter.length; ++j)
{
System.out.print(parameter[j].getName() + " " + "arg" + j);
if (j < parameter.length - 1)
{
System.out.print(",");
}
}
Class<?> exce[] = method[i].getExceptionTypes();
if (exce.length > 0)
{
System.out.print(") throws ");
for (int k = 0; k < exce.length; ++k)
{
System.out.print(exce[k].getName() + " ");
if (k < exce.length - 1)
{
System.out.print(",");
}
}
}
else
{
System.out.print(")");
}
System.out.println();
}
6)通过反射机制调用某个类的方法
Class<?> class8 = Class.forName("reflection.User");
//调用User类中的reflect1()方法
Method methodReflect1 = class8.getMethod("reflect1");
methodReflect1.invoke(class8.newInstance());
//调用User类中的reflect2(int age, String name)方法
Method methodReflect2 = class8.getMethod("reflect2", int.class, String.class);
methodReflect2.invoke(class8.newInstance(), 36, "cat");
7)通过反射机制操作某个类中的属性
Class<?> class9 = Class.forName("reflection.User");
User user1 = (User) class9.newInstance();
//可以对private类型的属性直接赋值
Field fieldNmae = class9.getDeclaredField("name");
Field fieldAge = class9.getDeclaredField("age");
//获取给private类型的属性直接赋值的权限
fieldNmae.setAccessible(true);
fieldAge.setAccessible(true);
//对name和age进行赋值操作
fieldNmae.set(user1, "Tomcat");
fieldAge.set(user1, 24);
System.out.println("Name—> " + user1.getName() + " Age—> " + user1.getAge());
System.out.println(fieldNmae.get(user1));
System.out.println(fieldAge.get(user1));
8)在泛型为Integer的ArrayList中存放一个String类型的对象
ArrayList<Integer> list = new ArrayList<Integer>();
Method methodAdd = list.getClass().getMethod("add", Object.class);
methodAdd.invoke(list, "Java反射机制实例");
System.out.println(list.get(0));
9)通过反射取得并修改数组的信息
int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
Class<?> class10 = array.getClass().getComponentType();
System.out.println("数组类型: " + class10.getName());
System.out.println("数组长度 " + Array.getLength(array));
System.out.println("数组的第一个元素: " + Array.get(array, 0));
Array.set(array, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(array, 0));
10)通过反射机制修改数组的大小
int[] newArray = (int[]) Array.newInstance(class10, 10);
//将array中的数据复制到newArray中
System.arraycopy(array, 0, newArray, 0, array.length);
System.out.println("array数组的大小为(修改前):" + array.length);
for(int i = 0; i < array.length; i++)
{
System.out.print(array[i] + " ");
}
System.out.println("");
System.out.println("array数组的大小为(修改后):" + newArray.length);
for(int i = 0; i < newArray.length; i++)
{
System.out.print(newArray[i] + " ");
}
4.总结
总的来说,java反射机制是一个很好用的东西,用它可以解决很多死的东西,因为反射机制的灵活行很大,有了他,我们就不要花太多的时间来写操做数据库的代码了,而是方法更多的时间在项目的逻辑功能上,这个可以很大的减少开发时间,而且代码的可读性好。先在的很多开源框架都是才用的反射机制,它只要配置文件,然后按规则来调用他的方法就可以了。
以上Demo的源代码地址:点击打开链接