JAVA高级–反射机制
文章目录
一、反射是什么?反射有什么用?
- 反射机制可以让程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
- 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。
1.一般流程与反射流程的对比
2.反射机制提供主要功能
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法
4.在运行时获取泛型信息
5.在运行时调用任意一个对象的成员变量和方法
6.在运行时处理注解
7.生成动态代理
二、反射的关键类–Class类
上文所说,反射机制是一种可以在运行时获取类信息的机制,而这个Class类我们将它理解成是每一个类对应的信息(Class本身也是一个类),每个类有且只有一个,里面包含了构造器,字段,方法等类的基本信息,我们可以用getClass()方法获取对应信息,然后进行操作。
1.获取Class的几种方式
// 1.知道具体的类,通过具体类的class属性获取对应的Class
Class hashMapClass = HashMap.class;
// 2.根据类的实例getClass获取对应的Class
Boolean aBoolean = new Boolean(true);
Class booleanClass = aBoolean.getClass();
// 3.根据全类名的信息,通过forName查找,(可能抛出异常)
try
{
Class<?> aClass = Class.forName("java.util.concurrent.locks.ReentrantLock");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
2.其他类型获取Class
Class listClass = List.class;// 接口的Class
Class intClass = Integer.class;// 类的Class
int arr[] = new int[10];
Class arrClass = arr.getClass();// 数组Class
Class enumClass = Month.class;// 枚举Class
Class baseTypeClass = boolean.class;// 基础数据类型Class
Class annoClass = Target.class;// 注解Class
3.何种情况出现相同的Class
只要是相同的类或者相同维度的Class,两者是同一个Class,如同样是一维数组,两者是同一个Class
System.out.println(new int[10].getClass() == new int[1000].getClass());//true
三、获取运行时对象信息
// 获取运行时类的信息
public static void getClassInfo()
{
Student student = new Student();
Class<? extends Student> studentClass = student.getClass();
// 实现接口的信息
Class<?>[] interfaces = studentClass.getInterfaces();
for (Class<?> anInterface : interfaces)
{
System.out.println(anInterface.getName());
}
// 父类的信息
Class<?> superclass = studentClass.getSuperclass();
System.out.println(superclass.getName());
// 所有public构造器
Constructor<?>[] constructors = studentClass.getConstructors();
// 所有构造器
Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
//构造器修饰符
System.out.println(constructor.getModifiers());
//构造器名称 名字为全类名
System.out.println(constructor.getName());
//构造器参数
for (Class<?> parameterType : constructor.getParameterTypes()) {
System.out.println(parameterType);
}
}
Method[] methods = studentClass.getMethods();
Method[] declaredMethods = studentClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
//方法权限
System.out.println(declaredMethod.getModifiers());
//方法名
System.out.println(declaredMethod.getName());
//方法参数
for (Class<?> parameterType : declaredMethod.getParameterTypes()) {
System.out.println(parameterType);
}
//返回参数
System.out.println(declaredMethod.getReturnType());
//方法抛出的异常
for (Class<?> exceptionType : declaredMethod.getExceptionTypes()) {
System.out.println(exceptionType);
}
}
//获取public的属性信息
Field[] fields = studentClass.getFields();
//获取所有的属性信息
Field[] declaredFields = studentClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//属性权限
System.out.println(declaredField.getModifiers());
//属性类型
System.out.println(declaredField.getType());
//属性名称
System.out.println(declaredField.getName());
}
}
public class Student extends People implements Comparable, Cloneable
{
private String name;
private String stuNo;
private Integer age;
public Student(String name)
{
this.name = name;
}
private Student(String name, Integer age)
{
this.name = name;
this.age = age;
}
Student()
{
}
protected Student(String name, String stuNo, Integer age)
{
this.name = name;
this.stuNo = stuNo;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getStuNo()
{
return stuNo;
}
public void setStuNo(String stuNo)
{
this.stuNo = stuNo;
}
public Integer getAge()
{
return age;
}
public void setAge(Integer age)
{
this.age = age;
}
@Override
public String toString()
{
return "Student{" + "name='" + name + '\'' + ", stuNo='" + stuNo + '\'' + ", age=" + age + '}';
}
@Override
public int compareTo(Object o)
{
return 0;
}
private Integer selfIntroduction(String city)
{
System.out.println(name + "来自:" + city);
return age;
}
}
public class People
{
private Double money;
public Double getMoney()
{
return money;
}
public void setMoney(Double money)
{
this.money = money;
}
}
小结
1.获取属性,构造器,方法权限信息为getModifiers;
2.获取参数列表为getParameterTypes;
3.获取全部权限信息为getDeclared【Fields,Methods,Constructors】()。
四、创建运行时对象
// 3.Class获取对应的构造器
public static void getConstructorByClass()
throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException
{
// 1.获取Class
Class<Student> studentClass = Student.class;
// 2.调用指定参数结构的构造器,生成Constructor的实例
Constructor<Student> constructor1 = studentClass.getConstructor();// 空参构造器实例
//创建实例
Student student1 = constructor1.newInstance();
System.out.println("student1 = " + student1);
Constructor<Student> constructor2 = studentClass.getConstructor(String.class);// 参数为string的构造器实例
Student student2 = constructor2.newInstance("小明");
System.out.println("student2 = " + student2);
}
五、调用运行时类的指定方法
// 5.调用运行时类的指定方法
public static void useMethodByClass()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
{
Student student = new Student("夏洛");
System.out.println(student);
Class<? extends Student> studentClass = student.getClass();
Method method1 = studentClass.getMethod("setAge", Integer.class);
// 返回值
Object invoke1 = method1.invoke(student, 10);
System.out.println(invoke1);
System.out.println(student);
// 没有参数的方法
Method method2 = studentClass.getMethod("getName");
// 返回值
Object invoke2 = method2.invoke(student);
System.out.println(invoke2);
// 私有方法
Method method3 = studentClass.getDeclaredMethod("selfIntroduction", String.class);
// setAccessible(true) 将方法设置为显示调用
method3.setAccessible(true);
// 返回值
Object invoke3 = method3.invoke(student, "厦门");
System.out.println(invoke3);
}
注:
1.Object 对应原方法的返回值,若原方法无返回值,此时返回null
2.若原方法若为静态方法,此时形参Object obj可为null
3.若原方法形参列表为空,则Object[] args为null(或者不填)
六、调用运行时类的指定属性
// 6.调用运行时类的指定属性
public static void useFieldByClass() throws NoSuchFieldException, IllegalAccessException {
Student student = new Student("小白");
System.out.println(student);
Class<? extends Student> studentClass = student.getClass();
// 获取字段实例
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true);
//设置值
nameField.set(student,"花花");
System.out.println(student);
}
注:
1.Method和Field、Constructor对象都有setAccessible()方法;
2.setAccessible启动和禁用访问安全检查的开关。