github源码地址:https://github.com/zz1044063894/reflex
Java反射机制概述
反射可以说是Java中最强大的技术之一,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的。
- Refledtion (反射)是被视为
动态语言
的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内
部属性及方法。 - 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。
这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
正常方式:
- 引入需要的"包类”名称
- 通过new实例化
- 取得实例化对象
反射方式:
- 实例化对象
- getClass()方法
- 得到完整的 “包类”名称
Java反射机制应用
● Java反射机制提供的功能,
➢在运行时判断任意一个对象所属的类
➢在运行时构造任意一个类的对象
➢在运行时判断任意一个类所具有的成员变量和方法
➢在运行时获取泛型信息
➢在运行时调用任意一个对象的成员变量和方法
➢在运行时处理注解
➢生成动态代理
反射相关的主要API
●
java.lang.Class
:代表一个类
●java.lang.reflect.Method:代表类的方法
●java.lang.reflect.Field:代表 类的成员变量
●java.lang.reflect.Constructor:代表类的构造器
反射前后的比较
首先我们写了一个User类。本篇博客的User类都是使用这个代码。
package com.jingchu.reflex;
/**
* @description: 测试使用用户类
* @author: JingChu
* @createtime :2020-07-29 10:47:01
**/
public class User {
private String name;
public int age;
/**
* 共有空参数构造器
*/
public User() {
}
/**
* 全参共有构造器
*
* @param name
* @param age
*/
public User(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 只有name参数的私有构造器
*
* @param name
*/
private User(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* 共有方法
*/
public void show() {
System.out.println("我是:" + name + "\t 一个编程界的小学生");
}
/**
* 私有方法
* @param nation 国籍
* @return
*/
private String showNation(String nation) {
return "我是" + nation + "人,我骄傲我自豪";
}
}
在User类中,
定义了1个共有参数,1个私有参数,以及他们的get、set方法
2个共有的构造方法,1个私有的构造方法。
一个共有的方法,一个私有的方法
反射之前我们可以做哪些事
/**
* 在使用反射之前我们可以做哪些事
*/
@Test
public void test() {
//新建一个User对象,这里只能看到两个共有的构造方法
User user = new User("景初", 18);
//通过user对象调用内部的方法和属性
user.age = 20;
System.out.println(user.toString());
user.show();
}
输出结果:
User{name=‘景初’, age=20}
我是:景初 一个编程界的小学生
注意:
在User类外部,不可以通过User类的对象调用其内部私有结构。
比如: name 、showNation() 以及私有的构造器
使用反射做到反射之前做的事情
//1。使用反射创建对象
Class clazz = User.class;
Constructor constructor = clazz.getConstructor(String.class, int.class);
//可以使用Object接收,也可以类型强转,效果类似
System.out.println("-------------------->:使用反射创建对象");
Object object = constructor.newInstance("景初", 18);
User user = (User) object;
System.out.println("object接收的对象:\t" + object.toString());
System.out.println("user接收的对象:\t" + user.toString());
//2。通过反射调用对象指定的属性和方法
System.out.println("-------------------->:使用反射调用对象的属性和方法");
//获得age属性
Field age = clazz.getDeclaredField("age");
//将user对象的age值改为20
age.set(user, 20);
age.set(object, 10);
System.out.println("更改属性后的user对象\t" + user);
System.out.println("更改属性后的object对象\t" + user);
Method show = clazz.getDeclaredMethod("show");
System.out.println("object调用show方法:\t");
show.invoke(object);
System.out.println("user调用showNation方法:\t");
show.invoke(user);
输出结果:
-------------------->:使用反射创建对象
object接收的对象: User{name=‘景初’, age=18}
user接收的对象: User{name=‘景初’, age=18}
-------------------->:使用反射调用对象的属性和方法
更改属性后的user对象 User{name=‘景初’, age=10}
更改属性后的object对象 User{name=‘景初’, age=10}
object调用show方法:
我是:景初 一个编程界的小学生
user调用showNation方法:
我是:景初 一个编程界的小学生
反射之前做不到的事情
//3.通过反射调用私有的构造器,私有的方法,私有的属性
System.out.println("-------------------->:使用反射调用对象私有的属性、方法、构造器");
//调用一个参数的私有方法
Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
constructor1.setAccessible(true);
User user1 = (User) constructor1.newInstance("JingCHu");
System.out.println("调用私有构造器生成的user对象:\t" + user1);
//调用私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(user1,"JingChu也是景初");
System.out.println("更改私有属性name后的user对象:\t" + user1);
//调用私有方法
Method showNation = clazz.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
System.out.println("调用user对象的私有方法:\t" +showNation.invoke(user1,"中国"));
结果:
-------------------->:使用反射调用对象私有的属性、方法、构造器
调用私有构造器生成的user对象: User{name=‘JingCHu’, age=0}
更改私有属性name后的user对象: User{name=‘JingChu也是景初’, age=0}
调用user对象的私有方法: 我是中国人,我骄傲我自豪