什么是反射?
反射是Java开发语言的特征之一,它的作用他简单来说就是可以在程序运行过程中获取一个类的所有信息(包括成员变量,成员方法,构造器等),并且能够进行变量修改和方法调用。
怎么用反射?
0.创建实体类
//注意public 和 private
@Data
public class User {
private String name;
private String sex;
private Integer age;
public String address;
//无参构造
public User() {
}
//有参构造
public User(String name) {
this.name = name;
}
public User(String name,String sex) {
this.name = name;
this.sex = sex;
}
private User(String name,String sex,Integer age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public User(String name,String sex,Integer age,String address) {
this.name = name;
this.sex = sex;
this.age = age;
this.address = address;
}
//private方法
private void running(String name) {
System.out.println(name + "在跑步");
}
//public方法
public void eating() {
System.out.println(name + "在吃饭");
}
//方法
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age='" + age + '\'' +
", address=" + address +
'}';
}
}
1.获取Class类的对象
1.1获取Class类的对象
//1.方式一: 通过Class中的一个静态方法forName(包名+类名)
Class c1 = Class.forName("com.example.demo.entity.User");
System.out.println("方式一: 通过Class中的一个静态方法forName(包名+类名)");
System.out.println(c1);
//2.方式二: 直接通过类名.class获取Class对象
Class c2 = User.class;
System.out.println("方式二: 直接通过类名.class获取Class对象");
System.out.println(c2);
//3.方式三: 通过对象.getClass()获取
User user = new User();
Class c3 = user.getClass();
System.out.println("方式三: 通过对象.getClass()获取");
System.out.println(c3);
2.获取构造器对象
2.1获取构造器对象
getConstructors() | 返回所有构造器对象的数组(只能拿public的) |
getDeclaredConstructors() | 返回所有构造器对象的数组,存在就能拿到 |
getConstructor(Class<?>… parameterTypes) | 返回指定的单个构造器对象(只能拿public的) |
getDeclaredConstructor(Class<?>… parameterTypes) | 返回指定的单个构造器对象,存在就能拿到 |
// 1.获取Class类的对象
Class userClass = User.class;
//2.1获取public修饰的构造器(public)
Constructor[] constructors1 = userClass.getConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor.getName());
}
//2.2获取全部修饰的构造器(public + private)
Constructor[] constructors2 = userClass.getDeclaredConstructors();
for (Constructor constructor : constructors2) {
System.out.println(constructor.getName());
}
//2.3获取单个构造器(只能获取公开的)
Constructor constructor1 = userClass.getConstructor(String.class,String.class);
System.out.println(constructor1.getName());
//2.4获取单个构造器(可以获取私有的)
Constructor constructor2 = userClass.getConstructor(String.class,String.class,Integer.class);
System.out.println(constructor2.getName());
2.2初始化对象
newInstance(Object… initargs) | 根据指定的构造器创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
setAccessible作用, 如果遇到私有构造器可以使用setAccessible方法暴力反射, 将权限打开(只打开一次)
//1.获取Class类的对象
Class userClass = User.class;
//获取公开构造器
Constructor constructor1 = userClass.getDeclaredConstructor(String.class,String.class);
//利用构造器创建对象
User user1 = (User) constructor1.newInstance();
System.out.println(user1);
//----------------------------------------------------------------
//获取私有构造器
Constructor constructor2 = userClass.getDeclaredConstructor(String.class,String.class,Integer.class);
//操作私有构造器需要暴力反射打开权限
constructor2.setAccessible(true);
//利用构造器创建对象
User user2 = (User) constructor2.newInstance();
System.out.println(user2);
3.获取成员变量对象
3.1获取成员变量对象
getFields() | 返回所有成员变量对象的数组(只能拿public的) |
getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
getField(String name) | 返回单个成员变量对象(只能拿public的) |
getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
//1.获取Class类的对象
Class userClass = User.class;
//2.1获取public修饰成员变量对象(public)
Field[] fields1 = userClass.getFields();
for (Field field : fields1) {
System.out.println(field.getName());
}
//2.2获取全部成员变量对象(public + private)
Field[] fields2 = userClass.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field.getName());
}
//2.3获取单个成员变量(只能获取公开的)
Field field1 = userClass.getField("address");
System.out.println(field1.getName());
//2.4获取单个成员变量(可以获取私有的)
Field field2 = userClass.getDeclaredField("name");
System.out.println(field2.getName());
3.2取值、赋值
set(Object obj, Object value) | 赋值 |
get(Object obj) | 获取值, 返回Object类型。 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查,进行暴力反射 |
注意: 反射可以破坏封装性,私有的也可以执行
//创建Class类对象
Class userClass = User.class;
//获取单个private修饰的变量
Field fName = userClass.getDeclaredField("name");
System.out.println(fName.getName());
//操作私有变量同样需要暴力反射
fName.setAccessible(true);
//创建一个学生对象
User user = new User();
//赋值
fName.set(user, "小明");
//取值, 返回类型是Object, 需要强转回字符串
String name = (String) fName.get(user);
System.out.println(name);
4.获取成员方法对象
4.1获取成员方法对象
getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
//1.获取Class类的对象
Class userClass = User.class;
//2.1获取public修饰的成员方法对象(public)
Method[] methods1 = userClass.getMethods();
for (Method method : methods1) {
System.out.println(method.getName());
}
//2.2获取所有成员方法对象(public + private)
Method[] methods2 = userClass.getDeclaredMethods();
for (Method method : methods2) {
System.out.println(method.getName());
}
//2.3获取单个成员方法对象(只能获取公开的)
Method method1 = userClass.getMethod("eating");
System.out.println(method1.getName());
//2.4获取单个成员变量(可以获取私有的)
Method method2 = userClass.getMethod("running");
System.out.println(method2.getName());
4.2执行方法
invoke(Object obj, Object… args) | 运行方法 参数一:用哪个对象调用该方法 参数二:调用方法的传递的参数(如果没有就不写) 返回值:方法的返回值(如果没有就不接返回值) |
//1.获取类对象
Class userClass = User.class;
//2.根据方法名获取public/private修饰的单个方法, 有参数要声明参数的类型
Method method = userClass .getDeclaredMethod("running", String.class);
System.out.println(method.getName());
//3.私有方法(private)同样需要暴力反射打开权限
method.setAccessible(true);
//4.创建一个User对象
User user = new User();
method.invoke(user, "小明");
总结
Java反射非常有用,因为它支持按名称动态检索有关类和数据结构的信息,并允许在执行的Java程序中进行操作。此功能非常强大,但是也要谨慎使用,上述demo只是最简单的实现方法,旨在通俗易懂,在实际业务中,由于涉及到的业务更加复杂化、多维化,所以各位同学可以根据自身需要去学习更多关于反射的知识。
以上。