Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。
反射非常强大,JDBC以及主流的框架如Spring、Mybatis等等都使用到了反射机制,可以说只要使用Java,反射无处不在。本文详细介绍如何使用反射获取到Class对象,类的方法和属性。
1.Class对象
Class对象包括一个类的方法、变量、接口、类名、类修饰符等等信息,获取Class对象有三种方法。
- 对象.getClass方法
- 类名.class属性
- Class的forName方法,参数为类的全路径
//获取Class对象的三种方法
Test test = new Test();
Class c1 = test.getClass();
Class c2=Test.class;
Class c3=Class.forName("ClassTest.Test");
2.获取类的各种信息
获取类名
//获取类名
String name=c1.getName();
String simplename=c1.getSimpleName();
System.out.println("类名(带包名称):"+name);
System.out.println("类名(不带包名称):"+simplename);
获取类修饰符
//获取类修饰符
int modifierid=c1.getModifiers();
//通过返回int值判断是否是某一修饰符
boolean isPublic=Modifier.isPublic(modifierid);
boolean isPrivate=Modifier.isPrivate(modifierid);
boolean isAbstract=Modifier.isAbstract(modifierid);
boolean isFinal=Modifier.isFinal(modifierid);
boolean isInterface=Modifier.isInterface(modifierid);
System.out.println(modifierid+"是否public:"+isPublic);
System.out.println(modifierid+"是否Private:"+isPrivate);
System.out.println(modifierid+"是否Abstract:"+isAbstract);
System.out.println(modifierid+"是否Final:"+isFinal);
System.out.println(modifierid+"是否Interface:"+isInterface);
获取包信息
//获取包信息
Package pack=c1.getPackage();
System.out.println("包信息:"+pack.getName());
获取父类的Class对象
//获取父类的Class对象
Class parentclass=c1.getSuperclass();
System.out.println("父类对象:"+parentclass.getName());
获取接口信息
//获取接口信息
Class [] interfacename=c1.getInterfaces();
for (Class c:interfacename)
System.out.println("实现接口:"+c.getName());
获取构造函数Constructor
//获取构造函数Constructor
Constructor [] constructors=c1.getConstructors();
for (Constructor constructor:constructors){
System.out.print("构造方法名称:"+constructor.getName());
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType:parameterTypes){
System.out.print("\t构造方法参数:"+parameterType.getName());
}
System.out.println();
}
3.生成实例对象
//生成对象
Constructor con=c1.getConstructor(int.class,String.class);
Test instance= (Test) con.newInstance(18,"张三");
instance.Print();
System.out.println();
4.获取成员方法并调用
//获取成员方法
Method[] methods=c1.getDeclaredMethods();
System.out.print("Test的方法有:");
for (Method method1:methods){
System.out.print(method1.getName()+" ");
}
System.out.println();
Method method=c1.getDeclaredMethod("Hello", String.class);
System.out.println("获取到的Hello方法名字:"+method.getName());
//获取成员方法参数
Class[] parameterTypes = method.getParameterTypes();
System.out.print("参数列表:");
for (Class parameterType : parameterTypes){
System.out.println(parameterType.getTypeName());
}
//获取成员方法返回类型
Class returnType=method.getReturnType();
System.out.println("返回类型:"+returnType.getTypeName());
//调用成员方法
//调用私有方法需要调用setAccessible方法设置为true
method.setAccessible(true);
method.invoke(con.newInstance(18,"张三"),"李四");
System.out.println();
5.获取成员属性,取值和赋值
//获取成员变量,通过get,set方法获属性取值和赋值
Field[] fields = c1.getFields();
Field[] fields1=c1.getDeclaredFields();
Field field=c1.getField("age");
System.out.print("getFields:");
for (Field f:fields){
System.out.print(f.getName()+":"+f.get(instance)+" ");
}
System.out.println();
System.out.print("getDeclaredFields:");
for (Field f:fields1){
//调用私有属性需要调用setAccessible方法设置为true
f.setAccessible(true);
System.out.print(f.getName()+":"+f.get(instance)+" ");
}
System.out.println();
field.set(instance,20);
System.out.println("getField:"+field.getName()+":"+field.get(instance));
6.总结
上面的代码有点需要注意:
1.必须调用setAccessible(true)方法,这是针对私有变量而言,public和protected等都不需要。这个方法是允许通过反射访问类的私有变量或者私有方法。
2.getDeclaredFields为获取所有属性,getFields不能获取到私有属性。获取方法部分同理。
私有变量和私有方法也是不允许其他的类随意调用的,但是通过反射可以饶过这一限制。
反射功能非常强大,可以在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法。
7.运行截图
8.所有演示代码
Main类
import java.lang.reflect.*;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获取Class对象的三种方法
Test test = new Test();
Class c1 = test.getClass();
Class c2=Test.class;
Class c3=Class.forName("ClassTest.Test");
//获取类名
String name=c1.getName();
String simplename=c1.getSimpleName();
System.out.println("类名(带包名称):"+name);
System.out.println("类名(不带包名称):"+simplename);
System.out.println();
//获取类修饰符
int modifierid=c1.getModifiers();
boolean isPublic=Modifier.isPublic(modifierid);
boolean isPrivate=Modifier.isPrivate(modifierid);
boolean isAbstract=Modifier.isAbstract(modifierid);
boolean isFinal=Modifier.isFinal(modifierid);
boolean isInterface=Modifier.isInterface(modifierid);
System.out.println(modifierid+"是否public:"+isPublic);
System.out.println(modifierid+"是否Private:"+isPrivate);
System.out.println(modifierid+"是否Abstract:"+isAbstract);
System.out.println(modifierid+"是否Final:"+isFinal);
System.out.println(modifierid+"是否Interface:"+isInterface);
System.out.println();
//获取包信息
Package pack=c1.getPackage();
System.out.println("包信息:"+pack.getName());
System.out.println();
//获取父类的Class对象
Class parentclass=c1.getSuperclass();
System.out.println("父类对象:"+parentclass.getName());
System.out.println();
//获取接口信息
Class [] interfacename=c1.getInterfaces();
for (Class c:interfacename)
System.out.println("实现接口:"+c.getName());
System.out.println();
//获取构造函数Constructor
Constructor [] constructors=c1.getConstructors();
for (Constructor constructor:constructors){
System.out.print("构造方法名称:"+constructor.getName());
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType:parameterTypes){
System.out.print("\t构造方法参数:"+parameterType.getName());
}
System.out.println();
}
System.out.println();
//生成对象
Constructor con=c1.getConstructor(int.class,String.class);
Test instance= (Test) con.newInstance(18,"张三");
instance.Print();
System.out.println();
//获取成员方法
Method[] methods=c1.getDeclaredMethods();
System.out.print("Test的方法有:");
for (Method method1:methods){
System.out.print(method1.getName()+" ");
}
System.out.println();
Method method=c1.getDeclaredMethod("Hello", String.class);
System.out.println("获取到的Hello方法名字:"+method.getName());
//获取成员方法参数
Class[] parameterTypes = method.getParameterTypes();
System.out.print("参数列表:");
for (Class parameterType : parameterTypes){
System.out.println(parameterType.getTypeName());
}
//获取成员方法返回类型
Class returnType=method.getReturnType();
System.out.println("返回类型:"+returnType.getTypeName());
//调用成员方法
method.setAccessible(true);
method.invoke(con.newInstance(18,"张三"),"李四");
System.out.println();
//获取成员变量,通过get,set方法获属性取值和赋值
Field[] fields = c1.getFields();
Field[] fields1=c1.getDeclaredFields();
Field field=c1.getField("age");
System.out.print("getFields:");
for (Field f:fields){
System.out.print(f.getName()+":"+f.get(instance)+" ");
}
System.out.println();
System.out.print("getDeclaredFields:");
for (Field f:fields1){
f.setAccessible(true);
System.out.print(f.getName()+":"+f.get(instance)+" ");
}
System.out.println();
field.set(instance,20);
System.out.println("getField:"+field.getName()+":"+field.get(instance));
}
}
Test类
package ClassTest;
public class Test implements interfacetest {
public int age=0;
private String name="默认名字";
public Test(){
System.out.println("空构造函数调用了");
}
public Test(int age, String name) {
this.age = age;
this.name = name;
}
public String Print(){
System.out.println("名字:"+name+" 年龄:"+age);
return name+age;
}
private void Hello(String who){
System.out.println("Hello "+who+",这是我的私有方法hello");
}
}
接口interfacetest
package ClassTest;
public interface interfacetest {
}
版权声明:本文为weixin_44259244原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。